С++ Невозможно преобразовать из const int* в const_iterator

Я обновился до более нового компилятора 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;
};

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


person j_martin    schedule 11.09.2018    source источник
comment
Нет, это вообще разные типы. На самом деле, чтобы создать const_iterator, указывающий на что-то, вам понадобится еще один итератор или сам контейнер.   -  person bipll    schedule 11.09.2018
comment
Я не пытался компилировать этот код, но ошибок в нем явно больше. Эти ... явно подозрительны. Опубликуйте наименьший пример кода, который вы можете создать, который показывает проблему. Например, хотя в вашем вопросе упоминается std::vector const_iterator, в этом коде нет ничего, что упоминало бы std::vector или его итераторы.   -  person Pete Becker    schedule 11.09.2018
comment
Где std::vector?   -  person Lightness Races in Orbit    schedule 11.09.2018
comment
Есть ли какая-то причина, по которой вы используете PIMPL?   -  person jfh    schedule 05.03.2020


Ответы (1)


Мне удалось преобразовать итератор 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, потому что это две отдельные реализации, которые будут тереться друг о друга.

person Lightness Races in Orbit    schedule 11.09.2018