为什么既没有用clang声明也没有删除move构造函数? [英] Why is the move constructor neither declared nor deleted with clang?
问题描述
请考虑以下课程.
struct with_copy {
with_copy() = default;
with_copy(with_copy const&) {}
with_copy& operator=(with_copy const&) { return *this; }
};
struct foo {
with_copy c;
std::unique_ptr<int> p;
};
-
with_copy
是否具有副本构造函数?是的.它是明确定义的. -
with_copy
是否具有移动构造函数?否.显式复制构造函数阻止生成它. -
with_copy
是否具有已删除的move构造函数?不.没有移动构造函数与拥有被删除的构造函数不同.删除的move构造函数将尝试移动格式不正确的文件,而不是退化为副本. -
with_copy
是否可复制?是的.其副本构造函数用于副本. -
with_copy
是否可移动?是的.其副本构造函数用于移动. - Does
with_copy
have a copy constructor? Yes. It was explicitly defined. - Does
with_copy
have a move constructor? No. The explicit copy constructor prevents it from being generated. - Does
with_copy
have a deleted move constructor? No. Not having a move constructor is not the same as having a deleted one. A deleted move constructor would make an attempt to move ill-formed instead of degenerating to a copy. - Is
with_copy
copyable? Yes. Its copy constructor is used for copies. - Is
with_copy
movable? Yes. Its copy constructor is used for moves. -
foo
是否具有副本构造函数?是的.它已删除了一个,因为调用unique_ptr
的已删除副本构造函数,其默认定义将不正确. -
foo
是否具有move构造函数? GCC同意,c拒绝. -
foo
是否具有已删除的move构造函数? GCC和clang都拒绝. -
foo
是否可复制?否.其副本构造函数已删除. -
foo
是否可移动? GCC同意,c拒绝. - Does
foo
have a copy constructor? Yes. It has a deleted one, as its defaulted definition would be ill-formed due to invokingunique_ptr
's deleted copy constructor. - Does
foo
have a move constructor? GCC says yes, clang says no. - Does
foo
have a deleted move constructor? Both GCC and clang say no. - Is
foo
copyable? No. Its copy constructor is deleted. - Is
foo
movable? GCC says yes, clang says no. -
X
没有用户声明的副本构造函数, -
X
没有用户声明的副本分配运算符, -
X
没有用户声明的移动分配运算符, -
X
没有用户声明的析构函数,并且 - move构造函数不会隐式定义为已删除.
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,X
does not have a user-declared destructor, and- the move constructor would not be implicitly defined as deleted.
- [...]
- 对于复制构造函数,是rvalue引用类型的非静态数据成员,或者
- 对于move构造函数,是非静态数据成员或直接或虚拟基类,其类型为 没有移动构造函数,并且不可复制.
- [...]
- for the copy constructor, a non-static data member of rvalue reference type, or
- for the move constructor, a non-static data member or direct or virtual base class with a type that does not have a move constructor and is not trivially copyable.
-
X
没有用户声明的副本构造函数, -
X
没有用户声明的副本分配运算符, -
X
没有用户声明的移动分配运算符,并且 -
X
没有用户声明的析构函数. 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, andX
does not have a user-declared destructor.- [...]
- 对于复制构造函数,是rvalue引用类型的非静态数据成员.
...现在是棘手的人.
... and now the tricky ones.
(当人们考虑分配而不是构造时,行为类似.)
(The behaviour is similar when one considers assignment instead of construction.)
据我所知,GCC是正确的. foo
应该具有对每个成员执行移动的move构造函数,在with_copy
的情况下,该成员会退化为副本. Clang的行为似乎很荒谬:我有一个带有两个可移动成员的聚合,但是我的聚合是一个不可移动的砖.
As far as I can see, GCC is correct. foo
should have a move constructor that performs a move on each member, which in with_copy
's case degenerates to a copy. Clang's behaviour seems quite ridiculous: I have an aggregate with two movable members, and yet my aggregate is an immovable brick.
谁是对的?
推荐答案
C ++ 11或n3485,[class.copy]/9:
C++11, or rather n3485, [class.copy]/9:
如果类
X
的定义未明确声明move构造函数,则将隐式声明一个move构造函数 且仅当且仅当
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
和/11:
隐式声明的复制/移动构造函数是其类的
inline public
成员.默认副本/ 如果X
具有以下内容,则将类X
的move构造函数定义为已删除(8.4.3):
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:
由于with_copy
是 不可复制的,所以foo
将具有 no 移动构造函数(它将被定义为已删除,因此不会被隐式包含)声明).
As with_copy
is not trivially copyable, foo
will have no move-constructor (it would be defined as deleted, therefore it won't be implicitly declared).
C ++ 1y,或者说是github repo从2013-11-12提交e31867c0;合并 DR1402
C++1y, or rather github repo commit e31867c0 from 2013-11-12; incorporating DR1402:
/9:
如果类
X
的定义未明确声明移动 构造函数,当且仅当一个构造函数被隐式声明为默认构造函数 如果
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
和/11:
隐式声明的复制/移动构造函数是
inline public
同类的成员.类X
的默认复制/移动构造函数 如果X
具有:
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:
定义为删除的默认移动构造函数将被忽略 重载分辨率(13.3,13.4).
A defaulted move constructor that is defined as deleted is ignored by overload resolution (13.3, 13.4).
在这里,foo
将具有移动构造器.
Here, foo
will have a move-constructor.
这篇关于为什么既没有用clang声明也没有删除move构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!