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

跟風遠走 提交于 2019-12-06 01:47:58

By defining the move assignment operator, you disabled the move constructor due to the rule of 5. The class isn't is_nothrow_move_constructible because it isn't move constructable at all, that constructor is no longer available unless you define it.

§12.8 Copying and moving class objects

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.

In the case where you had no user-defined move constructor, both were implicitly defined and followed the below specification.

§15.4 Exception specifications

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.

By declaring a move assignment, you've lost your implicit move constructor.
See the full chart below.

The move constructor is simply not generated in this case - it has nothing to do with noexcept.

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

By declaring a move assignment operator, you prevent the class from having any move constructor at all.

By defining the move operator, you've suppressed the implicit move constructor. That's why std::is_nothrow_move_constructible fails. Provide it to get the desired output:

struct S {
  S(S&&) noexcept {}
  S& operator= (S&&) noexcept { return *this; }
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!