I've looked at cppreference.com and they seem to indicate no noexcept
specification on std::function(std::function&&)
. This seems rather odd to me. Does the standard really not give a nothrow guarantee in this case?
Move constructors are usually noexcept, since otherwise they are unusable in any code that provides strong exception guarantee. In many implementations, is_nothrow_move_constructible also checks if the destructor throws because it is effectively noexcept(T(arg)).
It is not obligated to move anything, the class is not required to have a resource to be moved and a 'move constructor' may not be able to move a resource as in the allowable (but maybe not sensible) case where the parameter is a const rvalue reference (const T&&).
Thus, move constructor prevents unnecessarily copying data in the memory. Work of move constructor looks a bit like default member-wise copy constructor but in this case, it nulls out the pointer of the temporary object preventing more than one object to point to same memory location.
An exception specification is not part of a function's type. An exception specification may only appear at the end of the top-level function declarator in a declaration or definition of a function, pointer to function, reference to function, or pointer to member function. An exception specification cannot appear in a typedef declaration.
Quoting the standard (as you request):
C++11 §20.8.11.2.1/6 (from N3290):
function(function&& f);
template <class A> function(allocator_arg_t, const A& a, function&& f);
Effects: If!f
,*this
has no target; otherwise, move-constructs the target off
into the target of*this
, leavingf
in a valid state with an unspecified value.
So, sorry, no noexcept
on the move constructor.
There is a related Defect Report 2062 which is still open, but it goes in the other direction, so to speak, namely that there is at least one noexcept
that apparently should not be there, for whatever the rationale of that is…
It may be that the intent is to support callables that have throwing move constructors. But that is just speculation in the direction of rationalization. For example, imagine reallocation of the buffer in a vector of such function objects, where an attempt is made to move the originals, and where in the middle somewhere one of them throws (I think this was the original example by Abrahams et.al). Oh dang, they can't guaranteed be moved back, and neither can we go forward. So the reallocation fails, and the operation that caused the reallocation, fails, with the vector in an invalid state. A requirement of non-throwing move of the callable objects would have supported such general usage of function objects, including optimized vector reallocation (etc.). Which IMHO makes it doubtful that the intent really has been to make this trade-off.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With