Defaulted move assignment cannot be explicitly noexcept if a member has a non-trivial noexcept assignment operator

Viewed 3264

This code fails to compile with gcc 4.8.2 (-std=c++11) but compiles with clang 3.4 (trunk) (-std=c++11):

#include <type_traits>
#include <vector>

struct X {
  X& operator=(X&&) noexcept = default;
  // adding noexcept this leads to an error in gcc, but works in clang:
  // function ‘X& X::operator=(X&&)’ defaulted on its first
  // declaration with an exception-specification that differs from the
  // implicit declaration ‘X& X::operator=(X&&)’

  std::vector<char> m;
};

// this assert holds, even without noexcept
static_assert(std::is_nothrow_move_assignable<X>::value, 
              "type-specification violation");

int main()
{
  return 0;
}

The static_assert is the interesting part on gcc: the defaulted move assignment will be noexcept, but I cannot declare it that way.

A variant not involving vector is:

template<bool b>
struct F {
  F& operator=(F&&) noexcept(b) {return *this;}
};

struct X {
  X& operator=(X&&) noexcept = default;
  F<true> f;
};

What is the expected behavior here? Intuitively clang seems correct.

1 Answers
Related