Title
Missing Throws: for last `variant` constructor
Status
ready
Section
[variant.ctor]
Submitter
Jonathan Wakely

Created on 2025-11-07.00:00:00 last changed 7 days ago

Messages

Date: 2025-12-04.17:38:41

Proposed resolution:

This wording is relative to N5014.

  1. Modify [variant.ctor], as indicated:

    constexpr variant() noexcept(see below);
    

    -2- Constraints: is_default_constructible_v<T0> is `true`.

    -3- Effects: Constructs a `variant` holding a value-initialized value of type T0.

    -4- Postconditions: `valueless_by_exception()` is `false` and `index()` is `0`.

    -5- Throws: Any exception thrown by the value-initialization of T0.

    -6- Remarks: […]

    constexpr variant(const variant&);
    

    -7- Effects: If `w` holds a value, initializes the `variant` to hold the same alternative as `w` and direct-initializes the contained value with GET<j>(w), where `j` is `w.index()`. Otherwise, initializes the `variant` to not hold a value.

    -8- Throws: Any exception thrown by direct-initializating any Ti for all i the initialization of the contained value.

    -9- Remarks: […]

    constexpr variant(variant&&) noexcept(see below);
    

    -10- Constraints: is_move_constructible_v<Ti> is `true` for all i.

    -11- Effects: If `w` holds a value, initializes the `variant` to hold the same alternative as `w` and direct-initializes the contained value with GET<j>(std::move(w)), where `j` is `w.index()`. Otherwise, initializes the `variant` to not hold a value.

    -12- Throws: Any exception thrown by move-constructing any Ti for all i the initialization of the contained value.

    -13- Remarks: […]

    template<class T> constexpr variant(T&&) noexcept(see below);
    

    -14- Let Tj be a type that is determined as follows: build an imaginary function FUN(Ti) for each alternative type Ti for which Ti x[] = {std::forward<T>(t)}; is well-formed for some invented variable `x`. The overload FUN(Tj) selected by overload resolution for the expression FUN(std::forward<T>(t)) defines the alternative Tj which is the type of the contained value after construction.

    -15- Constraints: […]

    -16- Effects: Initializes `*this` to hold the alternative type Tj and direct-non-list-initializes the contained value with std::forward<T>(t).

    -17- Postconditions: […]

    -18- Throws: Any exception thrown by the initialization of the selected alternative Tj contained value.

    -19- Remarks: […]

    template<class T, class... Args> constexpr variant(in_place_type_t<T>, Args&&... args);
    

    -20- Constraints: […]

    -21- Effects: Direct-non-list-initializes the contained value of type `T` with std::forward<Args>(args)....

    -22- Postconditions: […]

    -23- Throws: Any exception thrown by the selected constructor of `T` the initialization of the contained value.

    -24- Remarks: […]

    template<class T, class U, class... Args>
      constexpr variant(in_place_type_t<T>, initializer_list<U> li, Args&&... args);
    

    -25- Constraints: […]

    -26- Effects: Direct-non-list-initializes the contained value of type `T` with il, std::forward<Args>(args)....

    -27- Postconditions: […]

    -28- Throws: Any exception thrown by the selected constructor of `T` the initialization of the contained value.

    -29- Remarks: […]

    template<size_t I, class... Args>
      constexpr explicit variant(in_place_index_t<I>, Args&&... args);
    

    -30- Constraints:

    1. (30.1) — `I` is less than `sizeof...(Types)` and
    2. (30.2) — is_constructible_v<TI, Args...> is `true`.

    -31- Effects: Direct-non-list-initializes the contained value of type TI with std::forward<Args>(args)....

    -32- Postconditions: `index()` is `I`.

    -33- Throws: Any exception thrown by the selected constructor of Ti the initialization of the contained value.

    -34- Remarks: If TI’s selected constructor is a constexpr constructor, this constructor is a constexpr constructor.

    template<size_t I, class U, class... Args>
      constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args);
    

    -35- Constraints:

    1. (35.1) — `I` is less than `sizeof...(Types)` and
    2. (35.2) — is_constructible_v<TI, initializer_list<U>&, Args...> is `true`.

    -36- Effects: Direct-non-list-initializes the contained value of type TI with il, std::forward<Args>(args)....

    -37- Postconditions: `index()` is `I`.

    -?- Throws: Any exception thrown by the initialization of the contained value.

    -38- Remarks: If TI’s selected constructor is a constexpr constructor, this constructor is a constexpr constructor.

Date: 2025-12-15.00:00:00

[ 2025-12-04; Reflector poll. ]

Set status to Tentatively Ready after six votes in favour during reflector poll.

Date: 2025-11-15.00:00:00

[ 2025-11-11; Jonathan provides improved wording ]

Date: 2025-11-11.17:00:52

All `variant` constructors except the last one have a Throws: element saying what they're allowed to throw.

This originates from an editorial pull request, where the submitter said:

"It looks like this defect is an artifact of a change between P0088R0 and P0088R1. Note how in R0 neither one of the `emplaced_type_t`/`emplaced_index_t` (as they were then called) + `initializer_list` constructors have a throws clause. In R1 only one of them gained it."

This wording is relative to N5014.

  1. Modify [variant.ctor], as indicated:

    template<size_t I, class U, class... Args>
      constexpr explicit variant(in_place_index_t<I>, initializer_list<U> il, Args&&... args);
    

    -35- Constraints:

    1. (35.1) — `I` is less than `sizeof...(Types)` and
    2. (35.2) — is_constructible_v<TI, initializer_list<U>&, Args...> is `true`.

    -36- Effects: Direct-non-list-initializes the contained value of type TI with il, std::forward<Args>(args)....

    -37- Postconditions: `index()` is `I`.

    -?- Throws: Any exception thrown by calling the selected constructor of TI.

    -38- Remarks: If TI’s selected constructor is a constexpr constructor, this constructor is a constexpr constructor.

History
Date User Action Args
2025-12-04 17:38:41adminsetmessages: + msg15776
2025-12-04 17:38:41adminsetstatus: new -> ready
2025-11-11 17:00:52adminsetmessages: + msg15734
2025-11-07 01:47:58adminsetmessages: + msg15577
2025-11-07 00:00:00admincreate