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.
const int value
is constant forever. No tricks or hacks to modify it.- 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. - No default creation of
A
objects. Accessing tomap
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);
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;
}
};