проблема const_cast с std :: map - PullRequest
1 голос
/ 20 апреля 2011

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

struct Nu
{
    Nu() {v = rand();}
    int v;
};

struct G
{
    ~G()
    {
        for(auto it = _m.begin(); it != _m.end(); it++) delete it->first;
    }
    void AddNewNu()
    {
        _m[new Nu] = 0.5f;
    }
    void ModifyAllNu()
    {
        for(auto it = _m.begin(); it != _m.end(); it++) it->first->v++;
    }
    float F(const Nu *n) const
    {
        auto it = _m.find(n);
        // maybe do other stuff with it
        return it->second;
    }

    map<Nu*, float> _m;
};

Здесь предположим, что Nu на самом деле является очень большой структурой, макет которой уже зафиксирован необходимостью сопоставления с внешней библиотекой (и, таким образом, «float» не может быть просто свернут в Nu, и по различным другим причинам он может ' t быть map<Nu, float>). Структура G имеет карту, которая используется для хранения всех созданных им Nu (и, в конечном счете, для удаления их всех при уничтожении). Как написано, функция F не будет компилироваться - она ​​не может привести (const Nu * n) к (Nu n), как ожидается std :: map. Однако карта не может быть переключена на map<const Nu*, float>, потому что некоторые неконстантные функции все еще должны изменить Nu внутри _m. Конечно, я мог бы альтернативно сохранить все эти Nu в дополнительном std :: vector и затем переключить тип карты на const - но это вводит вектор, который должен быть совершенно ненужным. Поэтому единственная альтернатива, о которой я подумал в данный момент, - это использовать const_cast внутри функции F (которая должна быть безопасной const_cast), и мне интересно, можно ли этого избежать.

После еще большей охоты эта точно такая же проблема уже решена здесь: Вызов карты :: find с аргументом const

Ответы [ 2 ]

0 голосов
/ 20 апреля 2011

Это потому, что map ожидает Nu* const, но вы дали ему const Nu*.Я также нахожу это очень нелогичным и не понимаю почему, но это так.

0 голосов
/ 20 апреля 2011

"find" в вашем случае вернет const_iterator.положить:

map<Nu*,float>::const_iterator it = _m.find(n);

...

return it->second;

должно работать, я думаю.

Поскольку вы используете метод const, вы, конечно, можете только читать свою карту, но не писать / изменять ее

...