Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Итератор для класса на основе list


Автор: rattick 26.11.2010, 03:20
Здравствуйте.
Есть класс в основе которого лежит контейнер list. Необходимо определить для него ряд методов. С обычными методами проблем не возникло, а вот с методами возвращающими и принимающими итераторы возникли проблемы. Собственно вопрос в том, как объявить итератор для моего класса?
Код

template<class T>
class mylist{
                list<T> *p;
public:
    mylist(){p=new list<T>;}

//как определить iterator
//например
iterator begin(){return p->begin();}
и т.д.
};

и как я понимаю там же надо будет определять перегрузку операторов?

Автор: boostcoder 26.11.2010, 05:35
так:
Код

#include <list>
#include <iostream>

template<typename T>
struct mylist {
   mylist() {}
   
   typedef typename std::list<T>::iterator iterator;
   typedef typename std::list<T>::const_iterator const_iterator;
   
   iterator begin() { _list.begin(); }
   const_iterator begin() const { _list.begin(); }
   iterator end() { _list.end(); }
   const_iterator end() const { _list.end(); }
   
   void push_back(const T& item) { _list.push_back(item); }

private:
   std::list<T> _list;
};

int main() {
   mylist<int> list;
}


http://liveworkspace.org/code/a993e7b86902c23362d07702d9f5c086

Автор: rattick 26.11.2010, 06:13
Огромное спасибо!!!!!
вот как оказывается
Код

typedef typename std::list<T>::iterator iterator;

а я делал
Код

typedef std::list<T>::iterator iterator;

и компилятор ругался.
Кстати, а почему именно так надо?

Автор: Леопольд 26.11.2010, 09:15
Цитата(rattick @  26.11.2010,  06:13 Найти цитируемый пост)
Кстати, а почему именно так надо? 
Потому что  имя std::list<T>::iterator зависит от параметра шаблона "T". 

Шаблоны можно специализировать, и одинаковым именам придавать разный смысл, typename - указание компилятору что это имя типа (а не переменной, функции и т.д.)
Код
template<typename T> struct Traits;

template<> struct Traits<char>
{
    static char const * iterator() { return "theName"; }
};
template<> struct Traits<int>
{
    struct iterator {};
};

template<> struct Traits<double>
{
   enum { iterator = 0 };
};
Сперва осмысли, потом читай дальше.

typename нужен только внутри шаблонов (на этапе, когда "T" ещё не параметризирован конкретным типом): http://liveworkspace.org/code/ff8a9e45b7d444d75f39260af3373c93

Автор: maxim1000 26.11.2010, 09:54
иногда есть смысл обернуть итератор списка в свой
причина стадартная - не выставлять слишком много деталей реализации наружу

в данном случае интерфейс итератора из нового класса определяется интерфейсом итератора списка, а не потребностями пользователя нового класса, поэтому пользователи могут завязываться на любые особенности списков

например, списки поддерживают операцию http://www.cplusplus.com/reference/stl/list/splice/, итератор нового класса тоже будет годиться для этой операции, вполне возможно, что пользователи класса этим воспользуются, а когда автор класса захочет сменить контейнер, его будет ждать неприятный сюрприз - он поломает кучу кода

реализовать обёртку несложно - можно использовать boost::iterator_facade и написать пару методов (которые вызывают соответствующую функциональность list:iterator)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)