Minimally reproducible example cpp.sh/2nlzz :
#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
using namespace std;
int main()
{
struct Movable {
Movable() = default;
Movable ( Movable && ) = default; // move constructor
vector<int> payload;
};
unordered_map<int, Movable> map;
vector<Movable> target(10);
int i = 0;
for(auto& it : map) {
target[i] = move(it.second);
++i;
}
}
gives me
19:15: error: use of deleted function 'main()::Movable& main()::Movable::operator=(const main()::Movable&)'
10:10: note: 'main()::Movable& main()::Movable::operator=(const main()::Movable&)' is implicitly declared as deleted because 'main()::Movable' declares a move constructor or move assignment operator
I did define a move constructor for Movable
and want it to be only moved, never copied, so it's fine that it's not using the regular assignment operator, which I guess it tries to use because it.second
returns a const Movable &
rather than a Movable &
, but why so?
I understand that it.first
has to be const, since keys must not be messed with, but it should be fine to move from the values.
Why do I get a const reference here and how can I fix the code so that I can move?
it.second
is not const
.
The issue is that user-declaring the move constructor not only deletes the implicitly-declared copy constructor and copy assignment operator, but also inhibits the implicit declaration of the move assignment operator.
Therefore your class has no move assignment operator and the copy assignment operator is deleted, resulting in the error you are seeing when trying to assign it.second
to another Movable
.
target[i] = move(it.second);
is an assignment expression, not a variable definition or other initialization of an object that would call a constructor.
Add
Movable& operator=(Movable&&) = default;
to your class and the move assignment will be possible.