为什么既没有用clang声明也没有删除move构造函数? [英] Why is the move constructor neither declared nor deleted with clang?

查看:98
本文介绍了为什么既没有用clang声明也没有删除move构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下课程.

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.
    • ...现在是棘手的人.

      ... and now the tricky ones.

      • 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 invoking unique_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.

      (当人们考虑分配而不是构造时,行为类似.)

      (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

      • 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.

      和/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 class X is defined as deleted (8.4.3) if X has:

      • [...]
      • 对于复制构造函数,是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.

      由于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

      • 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, and
      • X does not have a user-declared destructor.

      和/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 class X is defined as deleted (8.4.3) if X has:

      • [...]
      • 对于复制构造函数,是rvalue引用类型的非静态数据成员.

      定义为删除的默认移动构造函数将被忽略 重载分辨率(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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆