Title
[fund.ts.v2] any_cast doesn't work with rvalue reference targets and cannot move with a value target
Status
open
Section
[any.nonmembers]
Submitter
Ville Voutilainen

Created on 2015-06-13.00:00:00 last changed 90 months ago

Messages

Date: 2016-01-30.21:24:13

Proposed resolution:

This wording is relative to N4562.

  1. In [any.cons] p11+p12, edit as follows:

    template<class ValueType>
      any(ValueType&& value);
    

    -10- Let T be equal to decay_t<ValueType>.

    -11- Requires: T shall satisfy the CopyConstructible requirements, except for the requirements for MoveConstructible. If is_copy_constructible_v<T> is false, the program is ill-formed.

    -12- Effects: If is_constructible_v<T, ValueType&&> is true, cConstructs an object of type any that contains an object of type T direct-initialized with std::forward<ValueType>(value). Otherwise, constructs an object of type any that contains an object of type T direct-initialized with value.

    […]

  2. In [any.nonmembers] p5, edit as follows:

    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: is_reference_v<ValueType> is true or is_copy_constructible_v<ValueType> is true. Otherwise the program is ill-formed.

    -5- Returns: 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). For the third form, if is_move_constructible_v<ValueType> is true and is_lvalue_reference_v<ValueType> is false, std::move(*any_cast<remove_reference_t<ValueType>>(&operand)), otherwise, *any_cast<remove_reference_t<ValueType>>(&operand).

    […]

Date: 2016-01-15.00:00:00

[ 2016-01-30, Ville comments and provides wording ]

Drafting note: the first two changes add support for types that have explicitly deleted move constructors. Should we choose not to support such types at all, the third change is all we need. For the second change, there are still potential cases where Requires is fulfilled but Effects is ill-formed, if a suitably concocted type is thrown into the mix.

Date: 2015-11-04.16:49:21

[ 2015-10, Kona Saturday afternoon ]

Eric offered to help JW with wording

Move to Open

Date: 2017-02-02.00:41:18

[ 2015-07, Telecon ]

Jonathan to provide wording

Date: 2015-10-26.20:17:22

Addresses: fund.ts.v2

In Library Fundamentals v1, [any.nonmembers]/5 says:

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).

  1. This means that

    any_cast<Foo&&>(whatever_kind_of_any_lvalue_or_rvalue);
    

    is always ill-formed. That's unfortunate, because forwarding such a cast result of an any is actually useful, and such uses do not want to copy/move the underlying value just yet.

  2. Another problem is that that same specification prevents an implementation from moving to the target when

    ValueType any_cast(any&& operand);
    

    is used. The difference is observable, so an implementation can't perform an optimization under the as-if rule. We are pessimizing every CopyConstructible and MoveConstructible type because we are not using the move when we can. This unfortunately includes types such as the library containers, and we do not want such a pessimization!

History
Date User Action Args
2017-07-30 20:10:41adminsetstatus: wp -> open
2016-06-28 12:52:58adminsetstatus: ready -> wp
2016-04-16 04:56:37adminsetstatus: open -> ready
2016-01-30 21:24:13adminsetmessages: + msg7949
2016-01-30 21:24:13adminsetmessages: + msg7948
2015-11-04 16:49:21adminsetmessages: + msg7609
2015-11-04 16:49:21adminsetstatus: new -> open
2015-09-27 20:55:06adminsetmessages: + msg7556
2015-06-13 00:00:00admincreate