yohhoyの日記

技術的メモをしていきたい日記

default指定でdeletedされるムーブ操作とオーバーロード解決

プログラミング言語C++において、“default指定でdeletedされるムーブコンストラクタ/代入演算子(→id:yohhoy:20130203)” はオーバーロード解決に影響しない。これはCWG DR 1402で修正された挙動。

struct X {
  const int i = 42;  // constデータメンバを含む場合...
  X() = default;
  ~X() = default;
  X(const X&) = default;
  X(X&&) = default;
  X& operator=(const X&) { return *this; }
  X& operator=(X&&) = default;  // ムーブ代入演算子はdeleted
};

X a, b;
b = std::move(a);  // C++11ではNG/C++14ではOK

C++14 12.8/p11, p23より引用(下線部は強調)。

11 An implicitly-declared copy/move constructor is an inline public member of its class. A defaulted copy/move constructor for a class X is defined as deleted (8.4.3) if X has:

  • a variant member with a non-trivial corresponding constructor and X is a union-like class,
  • a potentially constructed subobject type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M's corresponding constructor, results in an ambiguity or a function that is deleted or inaccessible from the defaulted constructor,
  • any potentially constructed subobject of a type with a destructor that is deleted or inaccessible from the defaulted constructor, or,
  • for the copy constructor, a non-static data member of rvalue reference type.

A defaulted move constructor that is defined as deleted is ignored by overload resolution (13.3, 13.4). [Note: A deleted move constructor would otherwise interfere with initialization from an rvalue which can use the copy constructor instead. --end note]

23 A defaulted copy/move assignment operator for class X is defined as deleted if X has:

  • a variant member with a non-trivial corresponding assignment operator and X is a union-like class, or
  • a non-static data member of const non-class type (or array thereof), or
  • a non-static data member of reference type, or
  • a potentially constructed subobject of class type M (or array thereof) that cannot be copied/moved because overload resolution (13.3), as applied to M's corresponding assignment operator, results in an ambiguity or a function that is deleted or inaccessible from the defaulted assignment operator.

A defaulted move assignment operator that is defined as deleted is ignored by overload resolution (13.3, 13.4).

GCC

gcc 4.7.4では下記エラーとなる。gcc 4.8以降ではコンパイル可能。

error: use of deleted function 'X& X::operator=(X&&)'
note: 'X& X::operator=(X&&)' is implicitly deleted because the default definition would be ill-formed:
error: non-static const member 'const int X::i', can't use default assignment operator

Clang

Clang 3.3では下記エラーとなる。Clang 3.4以降ではコンパイル可能。

error: object of type 'X' cannot be assigned because its move assignment operator is implicitly deleted
note: explicitly defaulted function was implicitly deleted here
note: move assignment operator of 'X' is implicitly deleted because field 'i' is of const-qualified type 'const int'

関連URL