I'm trying to use copy assignment in the following case.
There're two template classes, list map
and xpair
.
template <typename Key, typename Value, class Less=xless<Key>>
class listmap {
public:
using key_type = Key;
using mapped_type = Value;
using value_type = xpair<const key_type, mapped_type>; //value_type
...
}
template <typename First, typename Second>
struct xpair {
First first{};
Second second{};
xpair(){}
xpair (const First& first, const Second& second):
first(first), second(second) {}
};
In the main.cpp, I tried to write,
using commend = string;
using str_str_map = listmap<string,string>;
using str_str_pair = str_str_map::value_type; //value_type, to be replaced
using commend_pair = xpair<commend, str_str_pair>;
int main(...) {
commend_pair cmd_pair;
str_str_pair newPair ("Key", "value");
cmd_pair.second = newPair;
...
}
It gives me an error saying
object of type 'xpair<const std::__1::basic_string<char>,
std::__1::basic_string<char> >' cannot be assigned because its copy
assignment operator is implicitly deleted
If I replace
using str_str_pair = str_str_map::value_type;
to
using str_str_pair = xpair<string, string>;
Everything works fine. Why is that? Shouldn't value_type = xpair<string, string>
?
An implicitly-declared copy assignment operator for class T is defined as deleted if any of the following is true: T has a user-declared move assignment operator.
If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used or needed for constant evaluation (since C++14). For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ).
T has a user-declared move assignment operator. Otherwise, it is defined as defaulted. A defaulted copy assignment operator for class T is defined as deleted if any of the following is true:
A copy assignment operator of class T is a non-template non-static member function with the name operator= that takes exactly one parameter of type T, T&, const T&, volatile T&, or const volatile T&. For a type to be CopyAssignable, it must have a public copy assignment operator.
I don't see where newPair
is declared, but the error message seems like enough.
Why this fails: If either element in the pair
is const, the assignment operator for that element is itself deleted. You couldn't assign to a const string
but that's exactly what you're asking it to do when you assign to pair<const string, T>
. To simplify the example
std::pair<const int, int> p(0, 0);
p.first = 1; // no, can't assign to p.first
p = std::pair<const int, int>(1, 2); // no, requires assigning to p.first
Why maps have const
key types: map
containers organize their elements based of the keys. If you changed a key, the map wouldn't be able to find it anymore. Consider:
std::map<string, int> m = { ... };
auto it = m.find(k);
it->first = "a different value";
Since a std::map
for example, is internally organized as a red-black tree, changing the key safely would require a reorganization of the node. However in this example you're operating directly on the pair
in the node. Changing the key
would require removing the pair from m
, then putting it back in with a changed key
.
You have
using value_type = xpair<const key_type, mapped_type>;
Since you are using a const key_type
you are no longer able to assign to it since key_type
is const
.
using str_str_pair = xpair<string, string>;
Works as neither string
is const
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With