2012-03-08 3 views
11

Как и в этом вопросе, я задаюсь вопросом о причине этого. Потому что я получаю сообщение об ошибке, когда пытаюсь получить расстояние между const и не-const итераторами.Почему std :: distance не работает на смешивание итераторов const и nonconst?

vector<int> v; 
auto it=v.begin(); 
auto cit=v.cbegin(); 
distance(it,cit); 


no matching function for call to ‘distance(__gnu_cxx::__normal_iterator<int*, std::vector<int> >&, __gnu_cxx::__normal_iterator<const int*, std::vector<int> >&) 

Из-за моего ограниченного понимания итераторов я не вижу причин, почему это не должно работать.

ответ

19

У вас есть изменяемый итератор и константный итератор в вызове std::distance, поэтому вывод аргумента шаблона не выполняется. Вы можете исправить это, указав аргумент шаблона явно.

std::vector<int> v; 
auto i1 = v.begin(); 
auto i2 = v.cbegin(); 

auto dist = std::distance<std::vector<int>::const_iterator>(i1, i2); 
6

Это потому, что std::distance() принимает только один параметр шаблона:

template <class InputIterator> 
iterator_traits<InputIterator>::difference_type 
distance(InputIterator first, InputIterator last); 

Поэтому first и last должен быть конвертируемым к тому же типу, и разрешение шаблон, к сожалению, не считают, что vector<int>::iterator конвертируется в vector<int>::const_iterator.

+0

хм, почему они просто не создают шаблон с 2 шаблонами? Возможно ли это сделать в cpp core lang? Что я спрашиваю, что это дизайнерское решение или ограничение языка? – NoSenseEtAl

+0

, чтобы быть ясным, я знаю, что они могут сделать шаблон с двумя параметрами шаблона, но Im задается вопросом, будет ли он конфликтовать с 1 шаблоном param version – NoSenseEtAl

+0

@NoSenseEtAl, я бы сказал, дизайнерское решение. Это проще и вычисление расстояния между итераторами разных типов (скажем, итератор с произвольным доступом и форвардный итератор), вероятно, не то, что вы хотите делать очень часто. Вы действительно можете написать версию с двумя аргументами шаблона, но какая проблема в этом мире будет решена? –

3

std::distance будет работать с этими двумя итераторы, что не работает это умозаключение аргумент шаблона. Компилятор пытается решить, какой тип заменить первый аргумент шаблона и имеет два потенциальных кандидата, которые по стандарту заканчиваются сбоем.

Вы можете сделать одну из двух вещей, либо сравнивать только итераторы одного и того же типа, или укажите тип для шаблона:

std::distance<std::vector<int>::const_iterator>(v.begin(), v.cbegin()); 
4

Как все говорят, это потому, что std::distance принимает только один тип итератора, и Вычисление аргумента шаблона не в состоянии выбрать, какой он должен быть (хотя возможно только одно из них, учитывая, что iterator преобразует в const_iterator, но не обратно).

Может быть, стоит писать шаблон что-то вроде этого:

template <typename Container> 
typename Container::const_iterator constify(const Container &, typename Container::iterator it) { 
    return it; 
} 

Затем вы можете заставить шаблон вывод так:

std::distance(constify(v, it), cit); 

вместо того, чтобы писать, что большой длинный тип. Параметр Container& является позором, потому что AFAIK Container не может быть выведен из одного аргумента итератора.

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