Lingxi
Lingxi

Reputation: 14987

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

I've being testing with GCC 5.2 and clang 3.6, both in C++14 mode, and they give the same output.

For the following code

#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;  
}

the result 11 is obtained. But if uncomment the move assignment operator, the output becomes 01. How could an explicit noexcept specification on the move assignment operator possibly affect that of the move constructor?

Upvotes: 3

Views: 483

Answers (5)

Cory Kramer
Cory Kramer

Reputation: 118021

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.

Upvotes: 7

Trevor Hickey
Trevor Hickey

Reputation: 37924

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

enter image description here

Upvotes: 5

aschepler
aschepler

Reputation: 72483

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.

Upvotes: 2

Rostislav
Rostislav

Reputation: 3977

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&&).

Upvotes: 2

user5431696
user5431696

Reputation: 11

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; }
};

Upvotes: 1

Related Questions