Is the default Move constructor defined as noexcept?

16,394

I think the answer is 15.4/14 (Exception specifications):

An inheriting constructor (12.9) and an implicitly declared special member function (Clause 12) have an exception-specification. If f is an inheriting constructor or 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 allows all exceptions if any function it directly invokes allows all exceptions, and f has the exception-specification noexcept(true) if every function it directly invokes allows no exceptions.

Basically, it Does What You Think, and the implicitly-declared move constructor is noexcept whenever it can be.

Share:
16,394

Related videos on Youtube

bjackfly
Author by

bjackfly

HFT Algo programmer just living the dream

Updated on January 28, 2020

Comments

  • bjackfly
    bjackfly over 4 years

    It seems that a vector will check if the move constructor is labeled as noexcept before deciding on whether to move or copy elements when reallocating. Is the default move constructor defined as noexcept? I saw the following documentation but it didn't specify this.http://en.cppreference.com/w/cpp/language/move_constructor

    Implicitly-declared move constructor

    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 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 an inline public member of its class with the signature T::T(T&&) A class can have multiple move constructors, e.g. both T::T(const T&&) and T::T(T&&). If some user-defined move constructors are present, the user may still force the generation of the implicitly declared move constructor with the keyword default.

  • Howard Hinnant
    Howard Hinnant almost 11 years
    Additional information: And you can test whether or not your expectations have been met: static_assert(std::is_nothrow_move_constructible<MyType>::va‌​lue, "MyType should be noexcept MoveConstructible");
  • mucaho
    mucaho over 8 years
    So all functions invoked by the implicit special member functions must be declared noexcept for the implicit special member functions to be noexcept. Means you have to be diligent enough to mark all relevant functions noexcept, means there is a lot room for human error, right?
  • Kerrek SB
    Kerrek SB over 8 years
    @mucaho: Well, if all your members themselves only use implicitly defined special members, then this isn't all that complex. The simple rule is the rule of single responsibility, and by default the only human error you should watch out for is defining special member functions explicitly. That only leaves special-purpose classes (such as unique_ptr) that you need to vet.
  • Yan Zhou
    Yan Zhou over 7 years
    What about explicitly declared special member function with default? Such as void T(T &&) = default. Am I correct to assume that it behaves exactly the same if this move constructor is implicitly declared if not prevented by other conditions, such as a user-defined copy constructor?
  • Deduplicator
    Deduplicator almost 6 years
    @YanZhou Yes, explicitly defaulted Special member functions also follow those rules unless explicitly overridden for constexpr and noexcept. Your example has a spurious void though, so it is a compile-error.
  • Louis Semprini
    Louis Semprini almost 4 years
    @HowardHinnant Your helpful comment to static_assert(std::is_nothrow_move_constructible<MyType>::va‌​lue) is a little misleading because that check will pass even if MyType has a nothrow/noexcept copy constructor (in which case the compiler makes no default move constructor, thus probably not being what the programmer expects since then std::vector copies). This includes both the cases of explicitly written AND compiler-generated implicit copy constructor if they happen to be noexcept....(continued)
  • Louis Semprini
    Louis Semprini almost 4 years
    @HowardHinnant (continued)...so given that rub, I'm not sure if the check is useful in the cases where the programmer hasn't explicitly also written a copy constructor that they know is not noexcept (because it's too much brainwork to figure out if the compiler-generated move-constructor would exist (despite your incredibly useful video youtube.com/watch?v=vLinb2fgkHk) and also whether the compiler-generated copy constructor would be noexcept). It's too bad there is no direct check that ONLY looks at the move constructor.
  • Howard Hinnant
    Howard Hinnant almost 4 years
    vector doesn't literally "look at the move constructor". In all likelihood it calls move_if_noexcept, or some equivalent: github.com/llvm/llvm-project/blob/master/libcxx/include/… move_if_noexcept branches on is_nothrow_move_constructible: eel.is/c++draft/forward#7
  • Louis Semprini
    Louis Semprini almost 4 years
    @HowardHinnant Right, it doesn't (confirmed by vimeo.com/97337253 at 38:05), but I'm saying neither does std::is_nothrow_move_constructible*, so that's why the test might be misleading to the OP and others...even if that test is true, meaning that vector will "do the right thing" by calling MyType(std::move(bar)) rather than MyType(bar), it turns out the call still ends up getting routed to the contained element's copy constructor, not its move constructor (continued)...
  • Louis Semprini
    Louis Semprini almost 4 years
    @HowardHinnant I think most readers of this question will assume the test checks whether the move constructor is called, but that's not the case. It would be nice if there could be such a test in C++, but it seems like the ideal test is not possible. So it would be good to warn people of the limitations of the (still useful) std::is_nothrow_move_constructible* test.
  • Howard Hinnant
    Howard Hinnant almost 4 years
    The test answers whether or not the expression MyType(std::move(bar)) is a valid, noexcept expression. This is the expression that vector will use. Asking if a move member exists or not is a different issue, and not nearly as helpful in generic programming.
  • Louis Semprini
    Louis Semprini almost 4 years
    @HowardHinnant Right, but the test people are hoping for isn't really "which path does std::vector take?" but rather "when all is said and done, will my MyType objects get copied or moved?" It's very easy for us to be fooled into a false confidence that our data is being moved especially in two cases: case #1: we wrote a copy constructor and didn't look at your cool video and understand that the compiler would not provide an implicit move constructor for us, and (continued)
  • Louis Semprini
    Louis Semprini almost 4 years
    @HowardHinnant case #2 we provided a destructor, causing the compiler to provide an implicit copy constructor (that could be noexcept) and omit the move constructor. In both cases we could easily assume that the compiler is providing a move constructor, and the std::is_nothrow_move_constructible*==true result could reinforce our false idea. I'll agree that this is a separate issue of "if you write one special function you should write all," however that second issue is likely to trip us up that I think it's worth mentioning whenever mentioning the std::is_nothrow_move_constructible* test.
  • Howard Hinnant
    Howard Hinnant almost 4 years
    Type authors need to give loving care to all 6 special members, whether or not they let the compiler provide them, and whether or not that type is to be used as an element in vector: howardhinnant.github.io/classdecl.html
  • Louis Semprini
    Louis Semprini almost 4 years
    @HowardHinnant Haha yes agreed! Glad that we now have a link to that guide on this question.