воскресенье, 8 июня 2008 г.
5 программ
Получил эстафету от Юрия Волкова, цель которой, перечислить 5 самых нужных для работы прграмм. Жаль конечно что только 5, так как использую я намного больше, но все-же:
1. Visual Studio 2005 professional - главный рабочий инструмент.
2. Total Commander, не ice (точнее не FAR), но мне нравится))
3. Subversion, не hg, не git и не bazaar, а старый добрый svn, надеюсь пощупать версию 1.5 :)
4. Firefox, с помощью которого я читаю почту, узнаю новости, гуглю и пишу этот блог ;)
5. gpodder, по пути на работу я иногда слушаю подкасты, а gpodder неплохо мне в этом помогает.
А кому передать эстафету я не знаю, так как без понятия кто мнея читает
так что передаю ее тебе :-)
пятница, 6 июня 2008 г.
Опять шаблоны
Я люблю С++ за то, что код делающий что-то простое может быть сколь угодно простым, но в то-же время сколь угодно сложным.
Например нужно написать функцию добавляющую элемент в контейнер, но конкретный тип контейнера неизветсен, вот простой вариант:
#include <iostream> #include <vector> template <class C, class T> void add (T inserter, C value) { *inserter = value; } int main(int argc, char *argv[]) { std::vector <int> arr; add(std::inserter(arr, arr.begin()), 1); add(std::inserter(arr, arr.begin()), 2); add(std::inserter(arr, arr.begin()), 3); for (int i = 0; i != arr.size(); i++) { std::cout << arr[i] << std::endl; } system("pause"); }Функция add получает 2 параметра, первый должен быть insert_iterator-ом, второй - значение которое добавляется в контейнер. Что здесь не так? Тип первого параметра может быть любым, можно например засунуть туда указатель на int и все скомпилируется, но будет неправильно работать. По сигнатуре функции непонятно что она должна получать, указатель на int, или все-же insert_iterator (это не очень понятно и по коду функции (: Если объяснить компилятору более доходчиво, то получится что-то вроде этого:
#include <iostream> #include <vector> #include <list> template < template <class T, class A> class container, template <class T> class allocator, class Arg > void add ( std::insert_iterator< container<Arg, allocator<Arg> > > inserter, Arg value ) { *inserter = value; } int main(int argc, char *argv[]) { std::vector <int> arr; add(std::inserter(arr, arr.begin()), 1); add(std::inserter(arr, arr.begin()), 2); add(std::inserter(arr, arr.begin()), 3); for (int i = 0; i != arr.size(); i++) { std::cout << arr[i] << std::endl; } system("pause"); }Этот код немного сложнее чем предыдущий. Функция add работает так-же, но имеет теперь три шаблонных параметра а не два, причем первые два - шаблонные(шаблонные параметры) . И теперь указатель на int туда передать нельзя, что очень хорошо. Уверен что можно усложнить этот пример еще и даже получить из этого какую-то пользу, возможности С++ безграничны :)) Update В этом коде есть небольшая ошибка, в функцию add, insert_iterator нужно передавать по ссылке, если передавать по значению, то будут проблемы с вектором. Дело в том, что после перераспределения памяти, итератор, который передается в add не изменится, а изменится только его локальная копия. Это приведет к тому, что итератор, указывающий на начало вектора, который хранится внутри insert_iterator-a станет показывать в неизвестность (пример работает потому, что inserter создается для каждого вызова add заново). Для list и deque это неактуально, так как там insert не приводит к порче итераторов.
Подписаться на:
Сообщения (Atom)