const in the return type of any_cast(const any&)Section: 22.7.5 [any.nonmembers] Status: C++17 Submitter: Casey Carter Opened: 2016-09-02 Last modified: 2017-07-30
Priority: 0
View all other issues in [any.nonmembers].
View all issues with C++17 status.
Discussion:
The overload of any_cast that accepts a reference to constant any:
template<class ValueType> ValueType any_cast(const any& operand);
is specified to return *any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand) in [any.nonmembers]/5. This calls the pointer-to-constant overload of any_cast:
template<class ValueType> const ValueType* any_cast(const any* operand) noexcept;
which is specified as:
Returns: Ifoperand != nullptr && operand->type() == typeid(ValueType), a pointer to the object contained byoperand; otherwise,nullptr.
Since typeid(T) == typeid(const T) for all types T, any_cast<add_const_t<T>>(&operand) is equivalent to any_cast<T>(&operand) for all types T when operand is a constant lvalue any.
The add_const_t in the return specification of the first overload above is therefore redundant.
[2016-09-09 Issues Resolution Telecon]
P0; move to Tentatively Ready
Casey will provide combined wording for this and 2768, since they modify the same paragraph.
Previous resolution [SUPERSEDED]:
This wording is relative to N4606.
Modify 22.7.5 [any.nonmembers] as indicated:
template<class ValueType> ValueType any_cast(const any& operand); template<class ValueType> ValueType any_cast(any& operand); template<class ValueType> ValueType any_cast(any&& operand);-4- Requires:
-5- Returns:is_reference_v<ValueType>istrueoris_copy_constructible_v<ValueType>istrue. Otherwise the program is ill-formed.For the first form,*any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand). For the second and third forms,*any_cast<remove_reference_t<ValueType>>(&operand). […]
[2016-09-09 Casey improves wording as determined by telecon]
The presented resolution is intended as the common wording for both LWG 2768 and LWG 2769.
Previous resolution [SUPERSEDED]:
This wording is relative to N4606.
Modify 22.7.5 [any.nonmembers] as indicated:
template<class ValueType> ValueType any_cast(const any& operand); template<class ValueType> ValueType any_cast(any& operand); template<class ValueType> ValueType any_cast(any&& operand);-4- Requires:
-5- Returns: For the firstis_reference_v<ValueType>istrueoris_copy_constructible_v<ValueType>istrue. Otherwise the program is ill-formed.form,and second*any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand). For theand thirdforms,*any_cast<remove_reference_t<ValueType>>(&operand). For the third form,std::forward<ValueType>(*any_cast<remove_reference_t<ValueType>>(&operand)). […]
[2016-10-05, Tomasz and Casey reopen and improve the wording]
The constraints placed on the non-pointer any_cast overloads are neither necessary nor sufficient to
guarantee that the specified effects are well-formed. The current PR for LWG 2769 also makes it
possible to retrieve a dangling lvalue reference to a temporary any with e.g. any_cast<int&>(any{42}),
which should be forbidden.
[2016-10-16, Eric made some corrections to the wording]
Previous resolution [SUPERSEDED]:
This wording is relative to N4606.
Modify 22.7.5 [any.nonmembers] as indicated:
template<class ValueType> ValueType any_cast(const any& operand); template<class ValueType> ValueType any_cast(any& operand); template<class ValueType> ValueType any_cast(any&& operand);-4- Requires:
-5- Returns:For the first overload,is_reference_v<ValueType>istrueoris_copy_constructible_v<ValueType>istrue.is_constructible_v<ValueType, const remove_cv_t<remove_reference_t<ValueType>>&>istrue. For the second overload,is_constructible_v<ValueType, remove_cv_t<remove_reference_t<ValueType>>&>istrue. For the third overload,is_constructible_v<ValueType, remove_cv_t<remove_reference_t<ValueType>>>istrue. Otherwise the program is ill-formed.For the first form,For the first and second overload,*any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand). For the second and third forms,*any_cast<remove_reference_t<ValueType>>(&operand).static_cast<ValueType>(*any_cast<remove_cv_t<remove_reference_t<ValueType>>>(&operand)). For the third overload,static_cast<ValueType>(std::move(*any_cast<remove_cv_t<remove_reference_t<ValueType>>>(&operand))). […]
[2016-11-10, LWG asks for simplification of the wording]
[Issues Telecon 16-Dec-2016]
Move to Tentatively Ready
Proposed resolution:
This wording is relative to N4606.
Modify 22.7.5 [any.nonmembers] as indicated:
template<class ValueType> ValueType any_cast(const any& operand); template<class ValueType> ValueType any_cast(any& operand); template<class ValueType> ValueType any_cast(any&& operand);-?- Let
Ube the typeremove_cv_t<remove_reference_t<ValueType>>.-4- Requires:
-5- Returns:For the first overload,is_reference_v<ValueType>istrueoris_copy_constructible_v<ValueType>istrue.is_constructible_v<ValueType, const U&>istrue. For the second overload,is_constructible_v<ValueType, U&>istrue. For the third overload,is_constructible_v<ValueType, U>istrue. Otherwise the program is ill-formed.For the first form,For the first and second overload,*any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand). For the second and third forms,*any_cast<remove_reference_t<ValueType>>(&operand).static_cast<ValueType>(*any_cast<U>(&operand)). For the third overload,static_cast<ValueType>(std::move(*any_cast<U>(&operand))). […]