Home > Back-end >  How to add to std::map an object with constant field?
How to add to std::map an object with constant field?

Time:10-27

Suppose I have the following code:

#include <string>
#include <map>

struct A {
    const int value;
    A(int value) : value{value} {}
};

int main() {
    A a{3};
    std::map<std::string, A> myMap;
    myMap["Hello"] = a; // Error: Copy assignment operator of 'A' is implicitly deleted because 
                        //        field 'value' is of const-qualified type 'const int'.
    return 0;
}

Well I understand the error. But I can't override operator= for this type of structure, because it has const int value field. So what should I do?

Commenters here suggest different solutions with their own pros and cons. Let me clear up the behaviour I need.

  1. const int value is constant forever. No tricks or hacks to modify it.
  2. If the key doesn't exist in a map, then assignment means "add pair [key, value] to the map". But if the key exists, then replace the value.
  3. No default creation of A objects. Accessing to map using a key that doesn't exist in a map should throw an error or abort or something. But creating default 'A' objects for an unexisting key is not allowed.

If I understand all the presented solutions, the best thing I can do is to create some wrapper around std::map. How do you think?

CodePudding user response:

Use map::emplace to construct A in-place:

myMap.emplace("Hello", 3);

Demo.

If the key doesn't exist in a map, then assignment means "add pair [key, value] to the map". But if the key exists, then replace the value.

As @Serge Ballesta commented, when the key already exists, you need to erase the node from the map and emplace a new node:

const char* key = "Hello";
const int value = 3;
const auto it = myMap.find(key);
if (it != myMap.end())
  myMap.erase(it);
myMap.emplace(key, value);

CodePudding user response:

struct A as the value of map, need a constructer and a operator=():

struct A {
  const int32_t value;
  A(): value(0) {}
  A(int32_t value) : value(value) {}

  A& operator=(const A& other) {
    // this change the value, if don't want change it, ignore this.
    // this is an undefined behavior. ignore this.
    // const_cast<int32_t&>(value) = other.value;
    return *this;
  }
};
  • Related