This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Tentatively Ready status.
variant constructorSection: 22.6.3.2 [variant.ctor] Status: Tentatively Ready Submitter: Jonathan Wakely Opened: 2025-11-07 Last modified: 2025-12-04
Priority: Not Prioritized
View other active issues in [variant.ctor].
View all other issues in [variant.ctor].
View all issues with Tentatively Ready status.
Discussion:
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 theemplaced_type_t/emplaced_index_t(as they were then called) +initializer_listconstructors have a throws clause. In R1 only one of them gained it."
Previous resolution [SUPERSEDED]:
This wording is relative to N5014.
Modify 22.6.3.2 [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:
- (35.1) —
Iis less thansizeof...(Types)and- (35.2) —
is_constructible_v<TI, initializer_list<U>&, Args...>istrue.-36- Effects: Direct-non-list-initializes the contained value of type
TIwithil, std::forward<Args>(args)....-37- Postconditions:
index()isI.-?- 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.
[2025-11-11; Jonathan provides improved wording]
[2025-12-04; Reflector poll.]
Set status to Tentatively Ready after six votes in favour during reflector poll.
Proposed resolution:
This wording is relative to N5014.
Modify 22.6.3.2 [variant.ctor], as indicated:
constexpr variant() noexcept(see below);-2- Constraints:
is_default_constructible_v<T0>istrue.-3- Effects: Constructs a
variantholding a value-initialized value of typeT0.-4- Postconditions:
valueless_by_exception()isfalseandindex()is0.-5- Throws: Any exception thrown by the value-initialization of
T0.-6- Remarks: […]
constexpr variant(const variant&);-7- Effects: If
wholds a value, initializes thevariantto hold the same alternative aswand direct-initializes the contained value withGET<j>(w), wherejisw.index(). Otherwise, initializes thevariantto not hold a value.-8- Throws: Any exception thrown by
direct-initializating anythe initialization of the contained value.Tifor all i-9- Remarks: […]
constexpr variant(variant&&) noexcept(see below);-10- Constraints:
is_move_constructible_v<Ti>istruefor all i.-11- Effects: If
wholds a value, initializes thevariantto hold the same alternative aswand direct-initializes the contained value withGET<j>(std::move(w)), wherejisw.index(). Otherwise, initializes thevariantto not hold a value.-12- Throws: Any exception thrown by
move-constructing anythe initialization of the contained value.Tifor all i-13- Remarks: […]
template<class T> constexpr variant(T&&) noexcept(see below);-14- Let
Tjbe a type that is determined as follows: build an imaginary functionFUN(Ti)for each alternative typeTifor whichTi x[] = {std::forward<T>(t)};is well-formed for some invented variablex. The overloadFUN(Tj)selected by overload resolution for the expressionFUN(std::forward<T>(t))defines the alternativeTjwhich is the type of the contained value after construction.-15- Constraints: […]
-16- Effects: Initializes
*thisto hold the alternative typeTjand direct-non-list-initializes the contained value withstd::forward<T>(t).-17- Postconditions: […]
-18- Throws: Any exception thrown by the initialization of the
selected alternativecontained value.Tj-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
Twithstd::forward<Args>(args)....-22- Postconditions: […]
-23- Throws: Any exception thrown by
the selected constructor ofthe initialization of the contained value.T-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
Twithil, std::forward<Args>(args)....-27- Postconditions: […]
-28- Throws: Any exception thrown by
the selected constructor ofthe initialization of the contained value.T-29- Remarks: […]
template<size_t I, class... Args> constexpr explicit variant(in_place_index_t<I>, Args&&... args);-30- Constraints:
- (30.1) —
Iis less thansizeof...(Types)and- (30.2) —
is_constructible_v<TI, Args...>istrue.-31- Effects: Direct-non-list-initializes the contained value of type
TIwithstd::forward<Args>(args)....-32- Postconditions:
index()isI.-33- Throws: Any exception thrown by
the selected constructor ofthe initialization of the contained value.Ti-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:
- (35.1) —
Iis less thansizeof...(Types)and- (35.2) —
is_constructible_v<TI, initializer_list<U>&, Args...>istrue.-36- Effects: Direct-non-list-initializes the contained value of type
TIwithil, std::forward<Args>(args)....-37- Postconditions:
index()isI.-?- 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.