2011-01-15 3 views
0


Более или менее все в теме.
когда яПользовательский контейнер с пользовательским итератором не работает, если контейнер определен как const

func(my_cont& c) 
{ c.begin() }; 

вещи работает, но

func(const my_cont& c) 
{ c.begin() }; 

не работает, претензии компилятора, наклоняюсь преобразовать это сопзЬ my_cont < ..> .... из my_cont < .. >

Каковы требования для контейнера и моего пользовательского итератора для обработки этого?

+1

У вас есть 'const' версия' begin() ', которая возвращает итератор, который работает с контейнером' const'? –

ответ

4

Ваш класс контейнер должен иметь две реализации начать() и конец() - один возвращающегося итератор и другой возвращающегося const_iterator:

 iterator begin(); 
const_iterator begin() const; 
     iterator end(); 
const_iterator end() const; 

const_iterator не могут быть использованы для изменения объекта, который он указывает.

1

Вам нужно добавить константный begin(), что-то вроде этого:

class my_cont 
{ 
public: 
    const_iterator begin() const; 
}; 

Вы должны определить тип const_iterator также.

0

Именно по этой причине STL реализует cost_iterator для контейнеров. Просто проверьте, как это реализовано в STL, я не уверен, что вы можете найти лучшее решение.

0

Вы можете вызывать функции-члены const только для объекта const (или изменчивых функций-членов на изменчивом объекте). Компилятор сообщает, что iterator my_cont::begin() const отсутствует.

+0

'iterator my_cont :: begin() const' недостаточно, так как' int * pr' не может использоваться в 'pr = & r' для' const int r'. Необходимым является возвращаемое значение 'const_iterator' (для будущих операций), а не только' const' метода 'my_cont :: begin()'. –

1

Вот хорошая статья по написанию итераторов:
http://www.aristeia.com/Papers/CUJ_June_2001.pdf

Поскольку большинство людей отметили вам нужно константные версии начать() и конец(), который возвращает const_iterator.

Большинство людей забыли, что итератор должен иметь возможность неявно преобразовывать в const_iterator. В противном случае трудно получить константный итератор из объекта без стоимости (без множества неприятных бросков).

my_cont data; 
for(my_cont::const_iterator loop = data.begin(); loop != data.end(); ++loop) 
{ 
    /* STUFF */ 
} 

Замечание выше: Вышеупомянутые вызовы фактически вызовут нерентабельные версии begin() и end(). Но они назначаются на const_iterator. Таким образом, ваши итераторы должны быть конвертируемыми в const_iterator для работы вышеприведенного кода (Примечание: нет никакого неявного преобразования из const_iterator в итератор. Это должно принимать явный const_cast, поскольку он по своей сути опасен).

class my_cont 
{ 
    public: 
    class iterator { /* STUFF */ } 
    class const_iterator 
    { 
     public: const_iterator(iterator const& rhs); 
     /* STUFF */ 
    } 

    iterator  begin(); 
    iterator  end(); 

    const_iterator begin() const; 
    const_iterator end() const; 
    /* STUFF*/ 
}; 
+0

Самый глубокий ответ здесь. Благодарю.Из связанной статьи Мейерса: «Причина, по которой актер не будет компилировать, заключается в том, что для этих типов контейнеров« итератор »и« const_iterator »являются совершенно разными классами, едва более тесно связанными друг с другом, чем« string »и« complex '." –

Смежные вопросы