разыменование итератора вызывает ошибку «не удается преобразовать», когда кажется, что это не следует делать - PullRequest
0 голосов
/ 21 марта 2012

При использовании VS 2008 целевой средой является Windows CE с процессором ARM, если это имеет значение.Я знаю, что используемый нами компилятор тоже устарел ...

Основная проблема, с которой я сталкиваюсь, заключается в том, что я пытаюсь создать свой собственный итератор для обёртки карты, который я написал, и перегружаю оператор-> () доставляет мне неприятности.Вот фрагмент кода, который вызывает у меня проблемы:

const pair<wstring, PropertyMap*>* ObjectMapIterator::operator->() const
{
    return &*m_MapIter;
}

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

Я получаю следующую ошибку:

ошибка C2440: «возврат»: невозможно преобразоватьот 'const std :: pair <_Ty1, _Ty2> *' до 'const std :: pair <_Ty1, _Ty2> *'

Заголовок для этого итератора выглядит следующим образом:

class ObjectMapIterator
{
public:
    ObjectMapIterator(const ObjectMap& rObjectMap);
    const ObjectMapIterator& operator++(int rhs);
    std::pair<std::wstring, PropertyMap*> operator*() const;
    const std::pair<std::wstring, PropertyMap*>* operator->() const;
    bool isDone() const;

private:
    const std::map<std::wstring, PropertyMap*>* m_pPropertyMaps;
    std::map<std::wstring, PropertyMap*>::const_iterator m_MapIter;
};

Как видите, и m_MapIter, и возвращаемое значение перегруженного оператора одинаковы ... Я извлек все операторы const из файлов .h и .cpp для этой части проекта иперекомпилирован с той же ошибкой, поэтому я не думаю, что это проблема с этим.

Если я сделаю что-то подобное, программа скомпилирует:

const pair<wstring, PropertyMap*>* ObjectMapIterator::operator->() const
{
    const pair<wstring, PropertyMap*>* returnVal = new pair<wstring, PropertyMap*>(*m_MapIter);
    return returnVal;
}

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

Вот весь файл .cpp на случай, если вы найдете это соответствующим:

#include "stdafx.h"
#include "ObjectMap.h"

using namespace std;

ObjectMapIterator::ObjectMapIterator(const ObjectMap& rObjectMap)
    :m_pPropertyMaps(&(rObjectMap.m_PropertyMaps)),
     m_MapIter(m_pPropertyMaps->begin())
{}

const ObjectMapIterator& ObjectMapIterator::operator++(int rhs)
{
    if(m_MapIter != m_pPropertyMaps->end())
    {
        m_MapIter++;
        return *this;
    }
    else
    {
        return *this;
    }
}

pair<wstring, PropertyMap*> ObjectMapIterator::operator*() const
{
    return *m_MapIter;
}

const pair<wstring, PropertyMap*>* ObjectMapIterator::operator->() const
{
    return &*m_MapIter;
}

bool ObjectMapIterator::isDone() const
{
    return m_MapIter == m_pPropertyMaps->end();
}

Определение ObjectMapIterator находится внутри файла ObjectMap.h.Поэтому я не забываю включить ObjectMapIterator.

Я слишком долго ломал голову над этим.Пожалуйста, дайте мне знать, если вы что-нибудь выясните.Спасибо!

1 Ответ

2 голосов
/ 22 марта 2012

std::map::const_iterator возвращает временное значение, а не ссылку, поэтому вы пытаетесь взять адрес этого временного и вернуть его.

Почему бы просто не вернуть pair по значению?

std::pair<std::wstring, PropertyMap*>* ObjectMapIterator::operator->() const
{
    return *m_MapIter;
}

На самом деле, если ваш оператор вернет std::map::const_iterator::pointer, как и std::map::const_iterator::operator->(), все будет хорошо:

std::map<std::wstring, PropertyMap*>::const_iterator::pointer operator->() const
{
return &*m_MapIter;
}

Кроме того, насколькопоскольку значение, возвращаемое std::map::const_iterator::operator->(), определяется реализацией, возможно, было бы лучше использовать

auto operator->() const -> decltype(m_MapIter.operator->())
{
return (m_MapIter.operator->());
}
...