2
votes

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:

  • X does not have a user-declared copy constructor,
  • X does not have a user-declared copy assignment operator,
  • X does not have a user-declared move assignment operator, and
  • X does not have a user-declared destructor.

What am I missing?

1
You quoted the text that answers your question. Your S has a user-declared copy-assignment operator, so there is not an implicitly declared move constructor. - M.M

1 Answers

8
votes

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 deleted. It blocks the copy constructor, move constructor and move assignment operator from being generated implicitly.

Something being deleted is not the same as it not existing at all; deleted 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 deleted copy assignment.