Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

map with const keys but non const values?

I have a situation, where I would like to have a map that does not allow to add/remove keys after initialization, but the values are allowed to change (thus I cannot simply make the map const). Ie

/*semi-const*/ map<int,int> myMap = initMap();

myMap[1] = 2;                  // NOT OK, because potentially adds a new key
myMap.at(1) = 2;               // OK, because works only if key is present
for (auto & element : myMap) {
    element.second = 0;        // OK, values may change
}

I could write my own wrapper for std::map, but I have the feeling that it is something not too uncommon, so I wonder if there is already an existing solution.

Is there some standard idiom for a map that does not allow adding/removing keys, while the values may change?

ps: I know that the title alone is a bit vague, because the keys are already const in a map, but I hope it is clear what I mean...

like image 435
463035818_is_not_a_number Avatar asked May 09 '17 07:05

463035818_is_not_a_number


2 Answers

Could you create a wrapper that contains the value that allows the value to be mutated when const and put that in the map instead? Something like:

template<typename T>
class Mutable {
    mutable T value;
public:
  const Mutable& operator=(const T& v) const { value = v; return *this; }
  T& get() const { return value; }  
};

Then your map can be of type

const std::map<int, Mutable<int>>

Live demo.

like image 125
Chris Drew Avatar answered Sep 20 '22 16:09

Chris Drew


I usually regard this as a pitfall in C++ more than a feature, but, if it fits your application, you can just use pointer values.

#include <map>
#include <memory>

int main(int argc, char ** argv)
{
    using namespace std;
    const map<int, shared_ptr<int>> myMap = { {1, make_shared<int>(100)} };
    // *(myMap[1]) = 2;  // Does not compile
    *(myMap.at(1)) = 2;
    for (auto & element : myMap)
    {
        *(element.second) = 0;
    }
    return 0;
}

Which is really just a simpler version of this other answer (obviously you may choose between shared_ptr / unique_ptr as needed).

like image 23
jdehesa Avatar answered Sep 20 '22 16:09

jdehesa