C ++ Невозможно преобразовать из const int * в const_iterator - PullRequest
0 голосов
/ 11 сентября 2018

Я обновился до более нового компилятора C ++ (переход от Visual C ++ 6.0 к Visual C ++ 2015) и работаю над преобразованием класса шаблона Vector для совместимости. Одна ошибка, с которой я сталкиваюсь, связана с методом vector :: erase и типом ввода.

  • Фрагмент шаблона класса:

    template<class Type> class Vector {
    public:
        typedef Type* iterator;
        typedef const Type* const_iterator;
    
        ...
    
        iterator erase( const_iterator iBegin );
        iterator erase( const_iterator iBegin, iEnd );
    
    private:
        VectorImpl<Type>* m_pImpl;
    };
    
    ...
    
    template <typename Type> typename Vector<Type>::iterator Vector<Type>::erase( 
    typename Vector<Type>::const_iterator iBegin )
    {
        return m_pImpl->erase( iBegin );
    };
    

    ...

  • Ошибка:

C2440: «инициализация»: невозможно преобразовать из «const int *» в «std :: _ Vector_const_iterator >>»

Мне удалось преобразовать итератор std :: vector в int *, разыменовав итератор, но я не уверен, как сделать обратное:

template <typename Type> typename Vector<Type>::const_iterator Vector<Type>::begin()
{
    Vector<Type>::const_iterator begin = &(*m_pImpl->begin());
    return begin;
};

Q: Можно ли преобразовать const int * в std :: vector const_iterator?

1 Ответ

0 голосов
/ 11 сентября 2018

Я смог преобразовать итератор std :: vector в int *, разыменовав итератор, но я не уверен, как сделать обратное

Вы должны иметь в виду, что указатели и итераторы - это не одно и то же. Указатели являются своего рода итератором, но обратное неверно.

Вы можете получить адрес некоторого элемента, переместив итератор к этому элементу, разыменовав итератор, а затем взяв адрес результата.

Но преобразовывать необработанный указатель в итератор не имеет особого смысла. В общем, это все равно, что налить немного апельсинового сока в воду, а затем попытаться разделить их потом. Желательно придерживаться итераторов по всем направлениям.

Однако см. Ниже.

Можно ли преобразовать const int * в std :: vector const_iterator?

На самом деле, да. Если вы знаете, что указатель действителен, и вы определенно используете только векторы, вы можете рассчитывать на непрерывность векторных данных:

const int* ptr = ...;
const int* first = &vec[0];
const size_t dist = ptr - first;
auto it = vec.cbegin() + dist;

Теперь it - это то, что вы хотите.

Но это хакерская атака, основанная на арифметике указателей и итераторов, первая из которых только будет работать с вектором, а вторая будет эффективна только для контейнера последовательности (и требует std::advance вместо этого на других контейнерах, в результате).

Я бы не принял это в рабочем коде без веской причины, управляемой ограничениями сторонней библиотеки.

Мне кажется, что вы должны заменить Vector на std::vector через доску. Я понимаю, что это может быть проблематично, если вы не можете (или не хотите) изменять внешний интерфейс кода. В этом случае, честно говоря, я бы исключил std::vector, потому что это две отдельные реализации, которые будут сталкиваться друг с другом.

...