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>
istrue
oris_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>
istrue
oris_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>
istrue
oris_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
U
be the typeremove_cv_t<remove_reference_t<ValueType>>
.-4- Requires:
-5- Returns:For the first overload,is_reference_v<ValueType>
istrue
oris_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)))
. […]