2013-06-25 3 views
6

У меня два таких определений типов:STL итераторы StD :: расстояние (ошибка)

typedef std::vector<int> Container; 
typedef std::vector<int>::const_iterator Iter; 

В задаче, которую я считаю, я выполнить некоторые операции по Container Input, и после того, что я хотел бы вычислить std::distance(Input.begin(),itTarget) , где itTarget имеет тип Iter. Но я получаю эту ошибку компилятора no instance of function template "std::distance" matches the argument list, и только после литья, т. Е. std::distance(static_cast<Iter>(Input.begin()),itTarget) все работает нормально.

Интересно, почему?

+2

Это потому, что 'begin()' не возвращает 'const_iterator'? –

+0

Но как-то он должен уметь? http://www.cplusplus.com/reference/vector/vector/begin/ –

+1

Так работают перегрузки 'const' и non'const'. Только если 'Input' является' const'-квалифицированным, будет вызываться перегрузка 'const'. Кроме того, вместо того, чтобы отличать итератор, вы можете вызвать тип шаблона: 'std :: distance (Input.begin(), itTarget)' –

ответ

8

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

std::distance(Input.cbegin(),itTarget); 
        ^^ 

см std::vector::cbegin ссылка

+1

3-й раз шарм: P –

+0

и cbegin() возвращает const iterator? –

+0

@SimonRighley yup, см. Обновленную ссылку – billz

5

Input.begin() возвращает iterator вместо const_iterator, и ваш второй аргумент является const_iterator, так что два аргумента в основном другого типа. Вы можете использовать cbegin(), если у вас есть доступ к возможностям C++ 11.

Второй способ сделать это: Каждый итератор конвертируется в const_iterator присвоением

std::vector<int> myVector(100); 
std::vector<int>::iterator it = myVector.begin(); 
std::vector<int>::const_iterator cit = it; 

Если у вас есть, чтобы упаковать вещи в функции вызова можно использовать некоторые магические:

std::distance(((const Container*)&Input)->begin(), itTarget); 

Если Input is const, компилятор вынужден использовать const-версию begin(), которая возвращает const_iterator.

+0

Литой работает с итераторами вектора, потому что они обычно просто typedef для 'T *' и 'const T *'. Это может не работать с итераторами, которые являются классами. – jrok

+0

Царапины, которые выглядят как 'итератор', всегда должны быть конвертируемыми в' const_iterator'. – jrok

+0

Кабриолет, да. Castable? Я бы не был так уверен. Обновлен мой ответ. – Marius