移动赋值运算符的异常说明符如何影响移动构造函数的异常说明符?

How could the exception specifier on move assignment operator affect that of move constructor?

我在 C++14 模式下使用 GCC 5.2 和 clang 3.6 进行测试,它们提供相同的输出。

对于下面的代码

#include <iostream>
#include <type_traits>

struct S {
  // S& operator= (S&&) noexcept { return *this; }
};


int main() {
  std::cout << std::is_nothrow_move_constructible<S>::value
            << std::is_nothrow_move_assignable<S>::value;  
}

得到结果11。但是,如果取消注释移动赋值运算符,输出将变为 01。移动赋值运算符的显式 noexcept 规范如何影响移动构造函数的规范?

通过定义移动运算符,您已经取消了隐式移动构造函数。这就是 std::is_nothrow_move_constructible 失败的原因。提供它以获得所需的输出:

struct S {
  S(S&&) noexcept {}
  S& operator= (S&&) noexcept { return *this; }
};

在这种情况下根本不会生成移动构造函数 - 它与 noexcept.

无关

来自 cppreference:

If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:

  • there are no user-declared copy constructors
  • there are no user-declared copy assignment operators
  • there are no user-declared move assignment operators
  • there are no user-declared destructors (until C++14)

the implicitly-declared move constructor is not defined as deleted due to conditions detailed in the next section then the compiler will declare a move constructor as a non-explicit inline public member of its class with the signature T::T(T&&).

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.

通过声明移动赋值运算符,您可以防止 class 有任何移动构造函数。

通过定义移动赋值运算符,由于 rule of 5,您禁用了移动构造函数。 class 不是 is_nothrow_move_constructible 因为它根本不是可移动构造的,除非您定义它,否则该构造函数不再可用。

§12.8 复制和移动 class 对象

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,
X does not have a user-declared destructor, and
— the move constructor would not be implicitly defined as deleted.

在您没有用户定义的移动构造函数的情况下,两者都被隐式定义并遵循以下规范。

§15.4 异常规范

An implicitly declared special member function shall have an exception-specification. If f is an implicitly declared default constructor, copy constructor, move constructor, destructor, copy assignment operator, or move assignment operator, its implicit exception-specification specifies the type-id T if and only if T is allowed by the exception-specification of a function directly invoked by f’s implicit definition; f shall allow all exceptions if any function it directly invokes allows all exceptions, and f shall allow no exceptions if every function it directly invokes allows no exceptions.

通过声明移动赋值,您丢失了隐式移动构造函数。
请参阅下面的完整图表。