Reputation: 335
This does not compile
#include <utility>
struct S {
int x;
S& operator=(const S& o) = delete;
// Uncomment this to compile
//S& operator=(S&& o) = default;
};
int main() {
S s1, s2;
s1.x = 0;
s2.x = 101;
// Following 2 lines do not compile
s1 = std::move(s2);
s1 = static_cast<S&&>(s2);
return 0;
}
Both clang 3.8.1 and g++ 6.3.0 refuse to compile this snippet.
Clang:
c.cc:19:6: error: overload resolution selected deleted operator '='
s1 = std::move(s2);
~~ ^ ~~~~~~~~~~~~~
c.cc:6:6: note: candidate function has been explicitly deleted
S& operator=(const S& o) = delete;
G++:
c.cc: In function ‘int main()’:
c.cc:19:20: error: use of deleted function ‘S& S::operator=(const S&)’
s1 = std::move(s2);
^
c.cc:6:6: note: declared here
S& operator=(const S& o) = delete;
^~~~~~~~
I understand that =delete
does not disallow the copy assignment operator to participate in overload resolution but why does it cause the deletion of the implicitly declared move assignment operator?
C++ standard says (12.8/9):
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if:
What am I missing?
Upvotes: 2
Views: 1475
Reputation: 275470
does not have a user-declared copy assignment operator,
on the contrary:
S& operator=(const S& o) = delete;
this is still a user-declared copy assignment operator, just one that is delete
d. It blocks the copy constructor, move constructor and move assignment operator from being generated implicitly.
Something being delete
d is not the same as it not existing at all; delete
d things are declared, but if selected by overload resolution, they generate an error.
You can =default
the move assignment and construct special member functions if you want them to exist despite your delete
d copy assignment.
Upvotes: 8