Reputation: 1230
While implementing C++17's std::any
according to the specification available in this Wiki I stumbled across something that seemed nonsensical to me:
In the definition of the free function std::any_cast
, which is used to retrieve values from an std::any
instance, an overload for r-value references is supplied (It's the third one):
template< class ValueType >
ValueType any_cast(any&& operand); // (3)
Now, there is a requirement listed below the synopsis that applies to overloads 2 and 3 (that means also including the r-value overload):
2-3)
Returns*any_cast<std::remove_reference_t<ValueType>>(&operand)
The definition does not seem to actually allow moving the data!
The function call is just redirected to the pointer-based overload; the information about the temporary nature of operand
is lost!
Is it intended that I can't move out of an any instance? Is it just a error in the wiki? Am I wrong here?
Upvotes: 16
Views: 1421
Reputation: 43662
The issue is in WP status at the time of writing this, which means:
WP - (Working Paper) - The proposed resolution has not been accepted as a Technical Corrigendum, but the full WG21/PL22.16 committee has voted to apply the Defect Report's Proposed Resolution to the working paper.
See the lwg here for more info: http://wg21.cmeerw.net/lwg/issue2509
A proposed resolution is indeed
For the third form, if
is_move_constructible_v<ValueType>
is true andis_lvalue_reference_v<ValueType>
is false,std::move(*any_cast<remove_reference_t<ValueType>>(&operand))
, otherwise,*any_cast<remove_reference_t<ValueType>>(&operand)
And the defect report list listing the WP: http://cplusplus.github.io/LWG/lwg-defects.html#2509
Upvotes: 11
Reputation: 15824
The implementation of std::any
that doesn't require copying is perfectly possible to do. There's only one problem: what do you do when the user requests a copy of std::any
? One solution to this problem is to make std::any
move-only, the other is to make it throw an exception on copy constructor if the underlying type is move-only, yet another is to require being able to copy the underlying type. The third solution was chosen.
The requirements placed on ValueType
being copy constructible are perfectly fine - since a type that's not copy constructible can't possibly be stored in the std::any
instance, std::any_cast
may as well make an always-failing cast a compiler error.
Now, the fact that the implementation of ValueType any_cast(any&& operand)
doesn't allow moving seems to be an oversight - after all, a copy is a perfectly fine implementation of moving, and the implementation is free to delegate the job to the move constructor if it's there, and to copy constructor if not.
Upvotes: 0