samedi 23 décembre 2017

Move assignment operator not being implicitly declared

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?

Aucun commentaire:

Enregistrer un commentaire