при компиляции и GCC и MSVC8 выдают ошибку:
$ g++ m3.cpp
m3.cpp: In function `int main(int, char**)':
m3.cpp:37: error: conversion from `Foo<int>::iterator' to non-scalar type `Foo<int>::const_iterator' requested
m3.cpp:37: error: conversion from `Foo<int>::iterator' to non-scalar type `Foo<int>::const_iterator' requested
при замене с Foo<int> на std::list<int> все компилируется на ура.
Внимание, вопрос -- неужели все дело в том, что в стандартных хидерах есть преобразование из iterator в const_iterator? У msvc итератор вообще наследуется от константного...
Мой реальный класс гораздо сложнее, и мне очень не хочется в цикле
for ( test_t::const_iterator i = t.begin(), e = t.end(); i !=e; ++i )
допускать появление неконстантного итератора, указывающего на начало списка.
Или я чего-то не понимаю с const — функциями?
Как компилятор выбирает, какую функцию дернуть -- const или не-const?
Почему в данном случае он игнорирует
У тебя типы iterator и const_iterator никак не связаны. Как же, по-твоему, можно допустить подобное преобразование?
Со стандартными контейнерами проблем не будет. С твоими собственными — ну так решай сам, как делать. Либо воспользуйся наследованием iterator от const_iterator, либо добавь какие-то конструкторы, либо явно различай по имени константные/неконстантные функции, либо просто в выражении obj.begin() obj должен быть константным, тогда и вызовется константная функция. Непонятно, собственно, что у тебя вызывает затруднения.
Of course, the code must be complete enough to compile and link.
...
K13>при замене с Foo<int> на std::list<int> все компилируется на ура.
K13>Внимание, вопрос -- неужели все дело в том, что в стандартных хидерах есть преобразование из iterator в const_iterator? У msvc итератор вообще наследуется от константного...
Да, дело именно в этом.
Смотри 23.1 (Container requirements), таблицу 65
В требованиях к типу iterator есть и такое: convertible to X::const_iterator.
K13>Мой реальный класс гораздо сложнее, и мне очень не хочется в цикле K13>
K13> for ( test_t::const_iterator i = t.begin(), e = t.end(); i !=e; ++i )
K13>
K13>допускать появление неконстантного итератора, указывающего на начало списка.
Это поправимо.
K13>Или я чего-то не понимаю с const — функциями? K13>Как компилятор выбирает, какую функцию дернуть -- const или не-const?
На основании типа объекта. K13>Почему в данном случае он игнорирует
K13>Как компилятор выбирает, какую функцию дернуть -- const или не-const? K13>Почему в данном случае он игнорирует const_iterator begin() const { return const_iterator(); } K13> const_iterator end() const { return const_iterator(); }
Здесь имеет место разрешение перегрузки. У тебя две функции begin, неконстантная версия подходит лучше (как и почему — это лучше смотреть в стандарте С++, вкратце, есть неявный аргумент типа Foo & у неконстантного begin и const Foo & у второго, в вызове t.begin(), где t — неконстантный, лучшее соответствие у неконстантной функции)
Of course, the code must be complete enough to compile and link.
Здравствуйте, K13, Вы писали:
K13>Позже буду думать, жить с work-around или сделать по стандарту...
Делай итераторы с помощью boost::iterator_façade. Тебе понадобится только объявить функции dereference, equal, increment(, decrement(, advance, distance_to)) и унаследоваться, остальное сделает Boost. Можно объявить изменяемый и неизменяемый итераторы одним шаблонным классом.