Почему std:: distance не работает на смешивание итераторов const и nonconst?
Как и в вопросе, мне интересно, почему. Потому что я получаю сообщение об ошибке, когда пытаюсь получить расстояние между итераторами const
и non const
.
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> >&)
Из моего ограниченного понимания итераторов я не вижу причин, почему это не должно работать.
Ответы
Ответ 1
У вас есть изменяемый итератор и константный итератор при вызове 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 );
Ответ 2
Это потому, что std:: distance() принимает только один параметр шаблона:
template <class InputIterator>
iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last);
Следовательно, first
и last
должны быть конвертированы в один и тот же тип, а разрешение шаблона, к сожалению, не учитывает, что vector<int>::iterator
можно конвертировать в vector<int>::const_iterator
.
Ответ 3
Как все говорят, потому что 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
не может быть выведен из одного аргумента итератора.
Ответ 4
std::distance
будет работать с этими двумя итераторами, что не работает, это вывод аргумента шаблона. Компилятор пытается решить, какой тип заменить первый аргумент шаблона и имеет два потенциальных кандидата, которые по стандарту заканчиваются сбоем.
Вы можете сделать одну из двух вещей, либо сравнить только итераторы того же типа, либо предоставить тип шаблону:
std::distance<std::vector<int>::const_iterator>( v.begin(), v.cbegin() );