views:

42

answers:

1

I'm having an issue. I have a class with an overloaded operator like this..

class Foo
{
        friend bool operator<(const Foo &a, const Foo &b);
        ...
};

bool operator<(const Foo &a, const Foo &b)
{
        return a.member < b.member;
}

Then in a function in a class that holds some Foos in a map as keys...

void Bar::Update()
{
        for (FooItr itr = foos.begin(); itr != foos.end();) {
                FooItr test = itr++;
                if (!test->first.Check()) { // Check() is const
                        my_map.insert(*test);
                        foos.remove(test);
                }
        }

        for (MapItr itr = my_map.begin(); itr != my_map.end(); ++itr) {
                itr->first.Update(); // Update is not const
        }
}

and I get an error message like...

error: passing ‘const Foo’ as ‘this’ argument of ‘void Foo::Update()’ discards qualifiers

I believe the reason is that the my_map.insert() is inserting const Foos, but I don't know how to solve this issue.

+4  A: 

Keys in a map are always const, even if you don't say so. It's like that to prevent programming errors.

Consider what would happen if Update changed member - the map data structure would be based on the original ordering, but now that member has changed, that ordering could be wrong! The map would be completely broken - you wouldn't be able to find, insert or remove data correctly.


So, some options to fix this are:

  • Use a different data structure, where it doesn't matter if the objects get "out of order", such as vector.
  • Move the data that gets updated somewhere else. Sometimes it really belongs in the mapped_type (map's second template parameter). Sometimes you can define a new struct to store the current mapped_type, and the data that needs to change.
  • If you were changing something that doesn't affect the type's observable state, like a cache, then I might suggest making the changed data members mutable and making the relevant member functions const, or storing the mutable data in a scoped_ptr. However, a function named Update suggests that the data being updated is fundamental to the type.
Doug
+1, I missed the `->first` :vP
Potatoswatter
Ah of course. Nargh! Thanks.
random
Well the full context of the problem isn't there, but using a multimap solved it (by avoiding the issue entirely, again won't go into it). Good possible solutions though.
random