Title
The in_place constructors and emplace functions added by P0032R3 don't require CopyConstructible
Status
resolved
Section
[any.cons][any.assign][any.modifiers]
Submitter
Ville Voutilainen

Created on 2016-07-05.00:00:00 last changed 97 months ago

Messages

Date: 2016-11-30.22:52:38

Proposed resolution:

This wording is relative to N4606.

  1. Change [any.class], class any synopsis, as indicated:

    class any {
    public:
      […]
      template <class TValueType, class... Args>
        explicit any(in_place_type_t<TValueType>, Args&&...);
      template <class TValueType, class U, class... Args>
        explicit any(in_place_type_t<TValueType>, initializer_list<U>, Args&&...);
        
      […]
      template <class TValueType, class... Args>
        void emplace(Args&& ...);
      template <class TValueType, class U, class... Args>
        void emplace(initializer_list<U>, Args&&...);
      […]
    };
    
  2. Change [any.cons] as indicated:

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

    -6- Let T be decay_t<ValueType>.

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

    […]

    -9- Remarks: This constructor shall not participate in overload resolution ifunless Tdecay_t<ValueType> is not the same type as any and is_copy_constructible_v<T> is true.

    template <class TValueType, class... Args>
      explicit any(in_place_type_t<TValueType>, Args&&... args);
    

    -?- Let T be decay_t<ValueType>.

    -11- Requires: T shall satisfy the CopyConstructible requirementsis_constructible_v<T, Args...> is true.

    […]

    -?- Remarks: This constructor shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, Args...> is true.

    template <class TValueType, class U, class... Args>
      explicit any(in_place_type_t<TValueType>, initializer_list<U> il, Args&&... args);
    

    -?- Let T be decay_t<ValueType>.

    -15- Requires: T shall satisfy the CopyConstructible requirementsis_constructible_v<T, initializer_list<U>&, Args...> is true.

    […]

    -19- Remarks: The function shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, initializer_list<U>&, Args...> is true.

  3. Change [any.assign] as indicated:

    template<class ValueType>
      any& operator=(ValueType&& rhs);
    

    -7- Let T be decay_t<ValueType>.

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

    […]

    -11- Remarks: This operator shall not participate in overload resolution ifunless Tdecay_t<ValueType> is not the same type as any and is_copy_constructible_v<T> is true.

  4. Change [any.modifiers] as indicated:

    template <class TValueType, class... Args>
      void emplace(Args&&... args);
    

    -?- Let T be decay_t<ValueType>.

    -1- Requires: T shall satisfy the CopyConstructible requirementsis_constructible_v<T, Args...> is true.

    […]

    -5- Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and any previously contained object has been destroyed. This function shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, Args...> is true.

    template <class TValueType, class U, class... Args>
      void emplace(initializer_list<U> il, Args&&... args);
    

    -?- Let T be decay_t<ValueType>.

    -?- Requires: T shall satisfy the CopyConstructible requirements.

    -6- Effects: […]

    […]

    -9- Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and any previously contained object has been destroyed. The function shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, initializer_list<U>&, Args...> is true.

Date: 2016-11-30.22:52:38

[ 2016-11 - Issaquah ]

Approved in plenary.

After plenary, there was concern about applying both this and 2744, so it was moved back to "Open". Then, when the concerns were resolved, moved to "Resolved".

Date: 2016-08-05.03:58:49

[ 2016-08 - Chicago ]

Thurs PM: Moved to Tentatively Ready

Date: 2016-08-03.00:00:00

[ 2016-08-03: Ville comments and revises his proposed wording ]

This P/R brings back the CopyConstructible parts of the relevant Requires-clauses but removes the other parts of the Requires-clauses.

Date: 2016-08-03.00:00:00

[ 2016-08-03: Ville comments and revises his proposed wording ]

After discussing the latest P/R, here's an update. What this update does is that:

  1. It strikes the Requires-clauses and does not add CopyConstructible to the Requires-clauses.

    Rationale: any doesn't care whether the type it holds satisfies the semantic requirements of the CopyConstructible concept. The syntactic requirements are now SFINAE constraints in Requires-clauses.

  2. It reverts back towards decay_t rather than remove_cv_t, and does not add the suggested SFINAE constraints for is_reference/is_array/is_function.

    Rationale:

    1. any decays by design. It's to some extent inconsistent to not protect against decay in the ValueType constructor/assignment operator, but to protect against decay in the in_place_t constructors and emplace functions

    2. I think it's saner to just decay than to potentially run into situations where I need to remove_reference inside in_place_t.

Based on that, this P/R should supersede the previous one. We want to look at this new P/R in LWG and potentially send it to LEWG for verification. Personally, I think this P/R is the more conservative one, doesn't add significant new functionality, and is consistent, and is thus not really Library-Evolutionary.

Previous resolution [SUPERSEDED]:

This wording is relative to N4606.

  1. Change [any.class], class any synopsis, as indicated:

    class any {
    public:
      […]
      template <class TValueType, class... Args>
        explicit any(in_place_type_t<TValueType>, Args&&...);
      template <class TValueType, class U, class... Args>
        explicit any(in_place_type_t<TValueType>, initializer_list<U>, Args&&...);
        
      […]
      template <class TValueType, class... Args>
        void emplace(Args&& ...);
      template <class TValueType, class U, class... Args>
        void emplace(initializer_list<U>, Args&&...);
      […]
    };
    
  2. Change [any.cons] as indicated:

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

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

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

    […]

    -9- Remarks: This constructor shall not participate in overload resolution ifunless decay_t<ValueType> is not the same type as any and is_copy_constructible_v<T> is true.

    template <class TValueType, class... Args>
      explicit any(in_place_type_t<TValueType>, Args&&... args);
    

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

    -11- Requires: is_constructible_v<T, Args...> is true.

    […]

    -?- Remarks: This constructor shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, Args...> is true.

    template <class TValueType, class U, class... Args>
      explicit any(in_place_type_t<TValueType>, initializer_list<U> il, Args&&... args);
    

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

    -15- Requires: is_constructible_v<T, initializer_list<U>&, Args...> is true.

    […]

    -19- Remarks: The function shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, initializer_list<U>&, Args...> is true.

  3. Change [any.assign] as indicated:

    template<class ValueType>
      any& operator=(ValueType&& rhs);
    

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

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

    […]

    -11- Remarks: This operator shall not participate in overload resolution ifunless decay_t<ValueType> is not the same type as any and is_copy_constructible_v<T> is true.

  4. Change [any.modifiers] as indicated:

    template <class TValueType, class... Args>
      void emplace(Args&&... args);
    

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

    -1- Requires: is_constructible_v<T, Args...> is true.

    […]

    -5- Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and any previously contained object has been destroyed. This function shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, Args...> is true.

    template <class TValueType, class U, class... Args>
      void emplace(initializer_list<U> il, Args&&... args);
    

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

    -6- Effects: […]

    […]

    -9- Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and any previously contained object has been destroyed. The function shall not participate in overload resolution unless is_copy_constructible_v<T> is true and is_constructible_v<T, initializer_list<U>&, Args...> is true.

Date: 2016-08-02.00:00:00

[ 2016-08-02: Ville adjusts the P/R to cope with the problems pointed out by Daniel's and Agustín's comments ]

Ville notes that 2746, 2754 and 2756 all go together.

Previous resolution [SUPERSEDED]:

This wording is relative to N4606.

Drafting note: this P/R doesn't turn the Requires-clauses into Remarks-clauses. We might want to do that separately, because SFINAEing the constructors allows users to query for is_constructible and get the right answer. Failing to mandate the SFINAE will lead to non-portable answers for is_constructible. Currently, libstdc++ SFINAEs. That should be done as a separate issue, as this issue is an urgent bug-fix but the mandated SFINAE is not.

  1. Change [any.class], class any synopsis, as indicated:

    class any {
    public:
      […]
      template <class TValueType, class... Args>
        explicit any(in_place_type_t<TValueType>, Args&&...);
      template <class TValueType, class U, class... Args>
        explicit any(in_place_type_t<TValueType>, initializer_list<U>, Args&&...);
        
      […]
      template <class TValueType, class... Args>
        void emplace(Args&& ...);
      template <class TValueType, class U, class... Args>
        void emplace(initializer_list<U>, Args&&...);
      […]
    };
    
  2. Change [any.cons] as indicated:

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

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

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

    […]

    -9- Remarks: This constructor shall not participate in overload resolution ifunless decay_t<ValueType> is not the same type as any and is_copy_constructible_v<T> is true.

    template <class TValueType, class... Args>
      explicit any(in_place_type_t<TValueType>, Args&&... args);
    

    -?- Let T be equal to remove_cv_t<ValueType>.

    -11- Requires: T shall satisfy the CopyConstructible requirements is_constructible_v<T, Args...> is true.

    […]

    -?- Remarks: This constructor shall not participate in overload resolution unless is_reference_v<T> is false, is_array_v<T> is false, is_function_v<T> is false, is_copy_constructible_v<T> is true and is_constructible_v<T, Args...> is true.

    template <class TValueType, class U, class... Args>
      explicit any(in_place_type_t<TValueType>, initializer_list<U> il, Args&&... args);
    

    -?- Let T be equal to remove_cv_t<ValueType>.

    -15- Requires: T shall satisfy the CopyConstructible requirements is_constructible_v<T, initializer_list<U>&, Args...> is true.

    […]

    -19- Remarks: The function shall not participate in overload resolution unless is_reference_v<T> is false, is_array_v<T> is false, is_function_v<T> is false, is_copy_constructible_v<T> is true and is_constructible_v<T, initializer_list<U>&, Args...> is true.

  3. Change [any.assign] as indicated:

    template<class ValueType>
      any& operator=(ValueType&& rhs);
    

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

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

    […]

    -11- Remarks: This operator shall not participate in overload resolution ifunless decay_t<ValueType> is not the same type as any and is_copy_constructible_v<T> is true.

  4. Change [any.modifiers] as indicated:

    template <class TValueType, class... Args>
      void emplace(Args&&... args);
    

    -?- Let T be equal to remove_cv_t<ValueType>.

    -1- Requires: T shall satisfy the CopyConstructible requirements is_constructible_v<T, Args...> is true.

    […]

    -5- Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and any previously contained object has been destroyed. This function shall not participate in overload resolution unless is_reference_v<T> is false, is_array_v<T> is false, is_function_v<T> is false, is_copy_constructible_v<T> is true and is_constructible_v<T, Args...> is true.

    template <class TValueType, class U, class... Args>
      void emplace(initializer_list<U> il, Args&&... args);
    

    -?- Let T be equal to remove_cv_t<ValueType>.

    -?- Requires: T shall satisfy the CopyConstructible requirements.

    -6- Effects: […]

    […]

    -9- Remarks: If an exception is thrown during the call to T's constructor, *this does not contain a value, and any previously contained object has been destroyed. The function shall not participate in overload resolution unless is_reference_v<T> is false, is_array_v<T> is false, is_function_v<T> is false, is_copy_constructible_v<T> is true and is_constructible_v<T, initializer_list<U>&, Args...> is true.

Date: 2016-08-02.00:00:00

[ 2016-08-02: Agustín K-ballo Bergé comments ]

Presumably the constructors any(in_place_type_t<T>, ...) would need to be modified in the same way the emplace overloads were.

Date: 2016-08-02.00:00:00

[ 2016-08-02: Daniel comments ]

The P/R wording of this issue brought to my intention that the recently added emplace functions of std::any introduced a breakage of a previous class invariant that only a decayed type could be stored as object into an any, this prevented storing arrays, references, functions, and cv-qualified types. The new constraints added my Ville do prevent some of these types (e.g. neither arrays nor functions meet the CopyConstructible requirements), but we need to cope with cv-qualified types and reference types.

Date: 2016-08-02.15:52:43

[ 2016-07 — Chicago ]

Monday: P1

Tuesday: Ville/Billy/Billy provide wording

Date: 2016-07-28.17:37:28

The in_place constructors and emplace functions added by P0032R3 don't require CopyConstructible.

They must. Otherwise copying an any that's made to hold a non-CopyConstructible type must fail with a run-time error. Since that's crazy, we want to prevent storing non-CopyConstructible types in an any.

Previously, the requirement for CopyConstructible was just on the converting constructor template and the converting assignment operator template on any. Now that we are adding two in_place constructor overloads and two emplace overloads, it seems reasonable to require CopyConstructible in some more general location, in order to avoid repeating that requirement all over the place.

History
Date User Action Args
2016-11-30 22:52:38adminsetmessages: + msg8704
2016-11-30 22:52:38adminsetstatus: open -> resolved
2016-11-14 03:53:34adminsetstatus: ready -> open
2016-08-05 03:58:49adminsetmessages: + msg8423
2016-08-05 03:58:49adminsetstatus: new -> ready
2016-08-04 19:47:07adminsetmessages: + msg8403
2016-08-03 21:33:49adminsetmessages: + msg8377
2016-08-02 21:37:33adminsetmessages: + msg8348
2016-08-02 20:59:26adminsetmessages: + msg8347
2016-08-02 20:45:26adminsetmessages: + msg8346
2016-08-02 15:52:43adminsetmessages: + msg8314
2016-08-01 18:34:48adminsetmessages: + msg8291
2016-07-05 00:00:00admincreate