Загнан в угол постоянной перегрузкой const: std::map ::find()

#c #stl #map #const-correctness

#c #stl #словарь #const-корректность

Вопрос:

Рассмотрим следующий фрагмент:

 #include <map>

class C {
public:
    C() {}

    const intamp; f(const intamp; x) const
    {
        // Error: cannot cast const int* to int* const
        return myMap.find(amp;x)->second;

        // With a const_cast works:
        //return myMap.find(const_cast<int* const>(amp;x))->second;
    }

    std::map<int*, int> myMap;
};

int _tmain(int argc, _TCHAR* argv[])
{
    int x = 0;

    C c;
    c.f(x);

    return 0;
}
  

Ошибка в f() вызвана постоянной перегрузкой map, find() принимающей const KeyTypeamp; значение. Поскольку ключевым типом карты является int* , это превращается в int* const . f() принимает const intamp; параметр, который является правильным, потому что параметр никогда не изменяется.

К сожалению, это заканчивается попыткой привести a const int* к a int* const , что приводит к потере спецификатора const в int и не будет компилироваться.

Это немного раздражает, потому что параметр определенно никогда не изменяется — он просто используется для find() — но мне все еще нужно const_cast это.

Есть ли способ написать f() без const_cast ?

Комментарии:

1. Это довольно необычно: почему вы используете указатели в качестве ключей карты?

2. В моих приложениях ключи должны быть ссылками на объекты с большим весом, и вы не можете использовать ссылку в качестве ключа карты.

Ответ №1:

Вы можете просто изменить тип map на std::map<const int*, int> ; Однако я сомневаюсь, нужны ли вам указатели в качестве ключей в первую очередь. Как указывает Джеймс, тип ключа должен быть const int* , потому что вы никогда не собираетесь изменять референт с помощью map . Если бы вы это сделали, я бы волновался еще больше.

Ответ №2:

Реальный вопрос в том, почему индекс карты не является указателем на const? (Предполагая, конечно, что это должен быть указатель.) Вы действительно хотите иметь возможность изменять индекс с помощью чего-то вроде *myMap.find(amp;x)->first = xxx ; Я бы сказал, что это довольно необычно, учитывая, что у вас уже есть указатель на объект.