Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cornered by const: std::map::find() const overload

Consider the following snippet:

#include <map>

class C {
public:
    C() {}

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

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

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

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

    C c;
    c.f(x);

    return 0;
}

The error in f() is caused by the const overload of map's find() taking a const KeyType&. Because the key type of the map is int*, this turns in to int* const. f() takes a const int& parameter, which is correct because the parameter is never modified.

Unfortunately this ends up in trying to cast a const int* to a int* const, which loses the const qualifier on the int and won't compile.

This is kind of irritating because the parameter definitely isn't ever modified - it's just used for a find() - but I still need to const_cast it.

Is there a way to write f() without the const_cast?

like image 317
AshleysBrain Avatar asked Apr 30 '11 23:04

AshleysBrain


2 Answers

You can just change the type of the map to std::map<const int*, int>; I question whether you need pointers as keys in the first place, though. As James points out, the key type should be const int* because you never intend to modify the referent via the map. If you did, I'd be even more worried.

like image 68
Jon Purdy Avatar answered Oct 19 '22 01:10

Jon Purdy


The real question is: why isn't the index of the map a pointer to const? (Supposing, of course, that it should be a pointer.) Do you really want to be able to modify the index via something like *myMap.find(&x)->first = xxx; I would say that that is quite unusual, given that you already have a pointer to the object.

like image 5
James Kanze Avatar answered Oct 19 '22 02:10

James Kanze