プログラミング言語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 classX
is defined as deleted (8.4.3) ifX
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 ifX
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
- C++ Standard Core Language Defect Reports, #1402 Move functions too often deleted
- http://en.cppreference.com/w/cpp/language/move_operator
- 特殊メンバ関数とコンパイラによる暗黙宣言 - yohhoyの日記