//// Copyright 2018-2021 Peter Dimov Distributed under the Boost Software License, Version 1.0. https://www.boost.org/LICENSE_1_0.txt //// [#reference] # Reference :idprefix: ref_ ## ### Synopsis ``` namespace boost { namespace variant2 { // in_place_type template struct in_place_type_t {}; template constexpr in_place_type_t in_place_type{}; // in_place_index template struct in_place_index_t {}; template constexpr in_place_index_t in_place_index{}; // variant template class variant; // variant_size template struct variant_size {}; template struct variant_size: variant_size {}; template struct variant_size: variant_size {}; template struct variant_size: variant_size {}; template struct variant_size: variant_size {}; // extension template struct variant_size: variant_size {}; // extension template inline constexpr size_t variant_size_v = variant_size::value; template struct variant_size>: std::integral_constant {}; // variant_alternative template struct variant_alternative {}; template struct variant_alternative; template struct variant_alternative; template struct variant_alternative; template struct variant_alternative; // extension template struct variant_alternative; // extension template using variant_alternative_t = typename variant_alternative::type; template struct variant_alternative>; // variant_npos constexpr std::size_t variant_npos = -1; // holds_alternative template constexpr bool holds_alternative(const variant& v) noexcept; // get template constexpr variant_alternative_t>& get(variant& v); template constexpr variant_alternative_t>&& get(variant&& v); template constexpr const variant_alternative_t>& get(const variant& v); template constexpr const variant_alternative_t>&& get(const variant&& v); template constexpr U& get(variant& v); template constexpr U&& get(variant&& v); template constexpr const U& get(const variant& v); template constexpr const U&& get(const variant&& v); // get_if template constexpr add_pointer_t>> get_if(variant* v) noexcept; template constexpr add_pointer_t>> get_if(const variant* v) noexcept; template constexpr add_pointer_t get_if(variant* v) noexcept; template constexpr add_pointer_t get_if(const variant* v) noexcept; // unsafe_get (extension) template constexpr variant_alternative_t>& unsafe_get(variant& v); template constexpr variant_alternative_t>&& unsafe_get(variant&& v); template constexpr const variant_alternative_t>& unsafe_get(const variant& v); template constexpr const variant_alternative_t>&& unsafe_get(const variant&& v); // relational operators template constexpr bool operator==(const variant& v, const variant& w); template constexpr bool operator!=(const variant& v, const variant& w); template constexpr bool operator<(const variant& v, const variant& w); template constexpr bool operator>(const variant& v, const variant& w); template constexpr bool operator<=(const variant& v, const variant& w); template constexpr bool operator>=(const variant& v, const variant& w); // swap template void swap(variant& v, variant& w) noexcept( /*see below*/ ); // visit template constexpr /*see below*/ visit(F&& f, V&&... v); // visit_by_index (extension) template constexpr /*see below*/ visit_by_index(V&& v, F&&.. f); // monostate struct monostate {}; constexpr bool operator==(monostate, monostate) noexcept { return true; } constexpr bool operator!=(monostate, monostate) noexcept { return false; } constexpr bool operator<(monostate, monostate) noexcept { return false; } constexpr bool operator>(monostate, monostate) noexcept { return false; } constexpr bool operator<=(monostate, monostate) noexcept { return true; } constexpr bool operator>=(monostate, monostate) noexcept { return true; } // stream insertion (extension) template std::basic_ostream& operator<<( std::basic_ostream& os, variant const& v ); template std::basic_ostream& operator<<( std::basic_ostream& os, monostate const& v ); // bad_variant_access class bad_variant_access; } // namespace variant2 } // namespace boost ``` ### variant ``` namespace boost { namespace variant2 { template class variant { public: // constructors constexpr variant() noexcept( /*see below*/ ); constexpr variant( variant const & r ) noexcept( /*see below*/ ); constexpr variant( variant&& r ) noexcept( /*see below*/ ); template constexpr variant( U&& u ) noexcept( /*see below*/ ); template constexpr explicit variant( in_place_type_t, A&&... a ); template constexpr explicit variant( in_place_type_t, std::initializer_list il, A&&... a ); template constexpr explicit variant( in_place_index_t, A&&... a ); template constexpr explicit variant( in_place_index_t, std::initializer_list il, A&&... a ); // destructor ~variant(); // assignment constexpr variant& operator=( variant const & r ) noexcept( /*see below*/ ); constexpr variant& operator=( variant&& r ) noexcept( /*see below*/ ); template constexpr variant& operator=( U&& u ) noexcept( /*see below*/ ); // modifiers template constexpr U& emplace( A&&... a ); template constexpr U& emplace( std::initializer_list il, A&&... a ); template constexpr variant_alternative_t>& emplace( A&&... a ); template constexpr variant_alternative_t>& emplace( std::initializer_list il, A&&... a ); // value status constexpr bool valueless_by_exception() const noexcept; constexpr size_t index() const noexcept; // swap void swap( variant& r ) noexcept( /*see below*/ ); // converting constructors (extension) template variant( variant const& r ) noexcept( /*see below*/ ); template variant( variant&& r ) noexcept( /*see below*/ ); // subset (extension) template constexpr variant subset() & ; template constexpr variant subset() && ; template constexpr variant subset() const& ; template constexpr variant subset() const&& ; }; } // namespace variant2 } // namespace boost ``` In the descriptions that follow, let `i` be in the range `[0, sizeof...(T))`, and `Ti` be the `i`-th type in `T...`. #### Constructors ``` constexpr variant() noexcept( std::is_nothrow_default_constructible_v ); ``` [none] * {blank} + Effects: :: Constructs a `variant` holding a value-initialized value of type `T0`. Ensures: :: `index() == 0`. Throws: :: Any exception thrown by the value-initialization of `T0`. Remarks: :: This function does not participate in overload resolution unless `std::is_default_constructible_v` is `true`. ``` constexpr variant( variant const & w ) noexcept( mp_all...>::value ); ``` [none] * {blank} + Effects: :: Initializes the variant to hold the same alternative and value as `w`. Throws: :: Any exception thrown by the initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless `std::is_copy_constructible_v` is `true` for all `i`. ``` constexpr variant( variant&& w ) noexcept( mp_all...>::value ); ``` [none] * {blank} + Effects: :: Initializes the variant to hold the same alternative and value as `w`. Throws: :: Any exception thrown by the move-initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless `std::is_move_constructible_v` is `true` for all `i`. ``` template constexpr variant( U&& u ) noexcept(/*see below*/); ``` [none] * {blank} + Let `Tj` be a type that is determined as follows: build an imaginary function `FUN(Ti)` for each alternative type `Ti`. The overload `FUN(Tj)` selected by overload resolution for the expression `FUN(std::forward(u))` defines the alternative `Tj` which is the type of the contained value after construction. Effects: :: Initializes `*this` to hold the alternative type `Tj` and initializes the contained value from `std::forward(u)`. Ensures: :: `holds_alternative(*this)`. Throws: :: Any exception thrown by the initialization of the contained value. Remarks: :: The expression inside `noexcept` is equivalent to `std::is_nothrow_constructible_v`. This function does not participate in overload resolution unless - `sizeof...(T)` is nonzero, - `std::is_same_v, variant>` is `false`, - `std::remove_cvref_t` is neither a specialization of `in_place_type_t` nor a specialization of `in_place_index_t`, - `std::is_constructible_v` is `true`, and - the expression `FUN(std::forward(u))` is well-formed. ``` template constexpr explicit variant( in_place_type_t, A&&... a ); ``` [none] * {blank} + Effects: :: Initializes the contained value of type `U` with the arguments `std::forward(a)...`. Ensures: :: `holds_alternative(*this)`. Throws: :: Any exception thrown by the initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless there is exactly one occurrence of `U` in `T...` and `std::is_constructible_v` is true. ``` template constexpr explicit variant( in_place_type_t, std::initializer_list il, A&&... a ); ``` [none] * {blank} + Effects: :: Initializes the contained value of type `U` with the arguments `il`, `std::forward(a)...`. Ensures: :: `holds_alternative(*this)`. Throws: :: Any exception thrown by the initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless there is exactly one occurrence of `U` in `T...` and `std::is_constructible_v&, A...>` is `true`. ``` template constexpr explicit variant( in_place_index_t, A&&... a ); ``` [none] * {blank} + Effects: :: Initializes the contained value of type `TI` with the arguments `std::forward(a)...`. Ensures: :: `index() == I`. Throws: :: Any exception thrown by the initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless `I < sizeof...(T)` and `std::is_constructible_v` is `true`. ``` template constexpr explicit variant( in_place_index_t, std::initializer_list il, A&&... a ); ``` [none] * {blank} + Effects: :: Initializes the contained value of type `TI` with the arguments `il`, `std::forward(a)...`. Ensures: :: `index() == I`. Throws: :: Any exception thrown by the initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless `I < sizeof...(T)` and `std::is_constructible_v&, A...>` is `true`. #### Destructor ``` ~variant(); ``` [none] * {blank} + Effects: :: Destroys the currently contained value. #### Assignment ``` constexpr variant& operator=( const variant& r ) noexcept( mp_all...>::value ); ``` [none] * {blank} + Let `j` be `r.index()`. Effects: :: `emplace(get(r))`. Returns: :: `*this`. Ensures: :: `index() == r.index()`. Remarks: :: This operator does not participate in overload resolution unless `std::is_copy_constructible_v && std::is_copy_assignable_v` is `true` for all `i`. ``` constexpr variant& operator=( variant&& r ) noexcept( mp_all...>::value ); ``` [none] * {blank} + Let `j` be `r.index()`. Effects: :: `emplace(get(std::move(r)))`. Returns: :: `*this`. Ensures: :: `index() == r.index()`. Remarks: :: This operator does not participate in overload resolution unless `std::is_move_constructible_v && std::is_move_assignable_v` is `true` for all `i`. ``` template constexpr variant& operator=( U&& u ) noexcept( /*see below*/ ); ``` [none] * {blank} + Let `Tj` be a type that is determined as follows: build an imaginary function `FUN(Ti)` for each alternative type `Ti`. The overload `FUN(Tj)` selected by overload resolution for the expression `FUN(std::forward(u))` defines the alternative `Tj` which is the type of the contained value after construction. Effects: :: `emplace(std::forward(u))`. Returns: :: `*this`. Ensures: :: `index() == j`. Remarks: :: The expression inside `noexcept` is `std::is_nothrow_constructible_v`. This operator does not participate in overload resolution unless - `std::is_same_v, variant>` is `false`, - `std::is_constructible_v && std::is_assignable_v` is `true`, and - the expression `FUN(std::forward(u))` (with `FUN` being the above-mentioned set of imaginary functions) is well-formed. #### Modifiers ``` template constexpr U& emplace( A&&... a ); ``` [none] * {blank} + Let `I` be the zero-based index of `U` in `T...`. Effects: :: Equivalent to: `return emplace(std::forward(a)...);` Remarks: :: This function shall not participate in overload resolution unless `std::is_constructible_v` is `true` and `U` occurs exactly once in `T...`. ``` template constexpr U& emplace( std::initializer_list il, A&&... a ); ``` [none] * {blank} + Let `I` be the zero-based index of `U` in `T...`. Effects: :: Equivalent to: `return emplace(il, std::forward(a)...);` Remarks: :: This function shall not participate in overload resolution unless `std::is_constructible_v&, A&&...>` is `true` and `U` occurs exactly once in `T...`. ``` template constexpr variant_alternative_t>& emplace( A&&... a ); ``` [none] * {blank} + Requires: :: `I < sizeof...(T)`. Effects: :: Initializes a new contained value as if using the expression `Ti(std::forward(a)...)`, then destroys the currently contained value. Ensures: :: `index() == I`. Returns: :: A reference to the new contained value. Throws: :: Nothing unless the initialization of the new contained value throws. Exception Safety: :: Strong. On exception, the contained value is unchanged. Remarks: :: This function shall not participate in overload resolution unless `std::is_constructible_v` is `true`. ``` template constexpr variant_alternative_t>& emplace( std::initializer_list il, A&&... a ); ``` [none] * {blank} + Requires: :: `I < sizeof...(T)`. Effects: :: Initializes a new contained value as if using the expression `Ti(il, std::forward(a)...)`, then destroys the currently contained value. Ensures: :: `index() == I`. Returns: :: A reference to the new contained value. Throws: :: Nothing unless the initialization of the new contained value throws. Exception Safety: :: Strong. On exception, the contained value is unchanged. Remarks: :: This function shall not participate in overload resolution unless `std::is_constructible_v&, A&&...>` is `true`. #### Value Status ``` constexpr bool valueless_by_exception() const noexcept; ``` [none] * {blank} + Returns: :: `false`. NOTE: This function is provided purely for compatibility with `std::variant`. ``` constexpr size_t index() const noexcept; ``` [none] * {blank} + Returns: :: The zero-based index of the active alternative. #### Swap ``` void swap( variant& r ) noexcept( mp_all..., is_nothrow_swappable...>::value ); ``` [none] * {blank} + Effects: :: - If `index() == r.index()`, calls `swap(get(*this), get(r))`, where `I` is `index()`. - Otherwise, as if `variant tmp(std::move(*this)); *this = std::move(r); r = std::move(tmp);` #### Converting Constructors (extension) ``` template variant( variant const& r ) noexcept( mp_all...>::value ); ``` [none] * {blank} + Effects: :: Initializes the contained value from the contained value of `r`. Throws: :: Any exception thrown by the initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless all types in `U...` are in `T...` and `std::is_copy_constructible_v::value` is `true` for all `Ui`. ``` template variant( variant&& r ) noexcept( mp_all...>::value ); ``` [none] * {blank} + Effects: :: Initializes the contained value from the contained value of `std::move(r)`. Throws: :: Any exception thrown by the initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless all types in `U...` are in `T...` and `std::is_move_constructible_v::value` is `true` for all `Ui`. #### Subset (extension) ``` template constexpr variant subset() & ; ``` ``` template constexpr variant subset() const& ; ``` [none] * {blank} + Returns: :: A `variant` whose contained value is copy-initialized from the contained value of `*this` and has the same type. Throws: :: - If the active alternative of `*this` is not among the types in `U...`, `bad_variant_access`. - Otherwise, any exception thrown by the initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless all types in `U...` are in `T...` and `std::is_copy_constructible_v::value` is `true` for all `Ui`. ``` template constexpr variant subset() && ; ``` ``` template constexpr variant subset() const&& ; ``` [none] * {blank} + Returns: :: A `variant` whose contained value is move-initialized from the contained value of `*this` and has the same type. Throws: :: - If the active alternative of `*this` is not among the types in `U...`, `bad_variant_access`. - Otherwise, any exception thrown by the initialization of the contained value. Remarks: :: This function does not participate in overload resolution unless all types in `U...` are in `T...` and `std::is_move_constructible_v::value` is `true` for all `Ui`. ### variant_alternative ``` template struct variant_alternative; ``` ``` template struct variant_alternative; ``` ``` template struct variant_alternative; ``` ``` template struct variant_alternative; // extension ``` ``` template struct variant_alternative; // extension ``` [none] * {blank} + -- If `typename variant_alternative::type` exists and is `U`, * `variant_alternative::type` is `U const`; * `variant_alternative::type` is `U volatile`; * `variant_alternative::type` is `U const volatile`. * `variant_alternative::type` is `U&`. * `variant_alternative::type` is `U&&`. Otherwise, these structs have no member `type`. -- ``` template struct variant_alternative>; ``` [none] * {blank} + When `I < sizeof...(T)`, the nested type `type` is an alias for the `I`-th (zero-based) type in `T...`. Otherwise, there is no member `type`. ### holds_alternative ``` template constexpr bool holds_alternative(const variant& v) noexcept; ``` [none] * {blank} + Requires: :: The type `U` occurs exactly once in `T...`. Otherwise, the program is ill-formed. Returns: :: `true` if `index()` is equal to the zero-based index of `U` in `T...`. ### get ``` template constexpr variant_alternative_t>& get(variant& v); ``` ``` template constexpr variant_alternative_t>&& get(variant&& v); ``` ``` template constexpr const variant_alternative_t>& get(const variant& v); ``` ``` template constexpr const variant_alternative_t>&& get(const variant&& v); ``` [none] * {blank} + Effects: :: If `v.index()` is `I`, returns a reference to the object stored in the variant. Otherwise, throws `bad_variant_access`. Remarks: :: These functions do not participate in overload resolution unless `I` < `sizeof...(T)`. ``` template constexpr U& get(variant& v); ``` ``` template constexpr U&& get(variant&& v); ``` ``` template constexpr const U& get(const variant& v); ``` ``` template constexpr const U&& get(const variant&& v); ``` [none] * {blank} + Requires: :: The type `U` occurs exactly once in `T...`. Otherwise, the program is ill-formed. Effects: :: If `v` holds a value of type `U`, returns a reference to that value. Otherwise, throws `bad_variant_access`. ### get_if ``` template constexpr add_pointer_t>> get_if(variant* v) noexcept; ``` ``` template constexpr add_pointer_t>> get_if(const variant* v) noexcept; ``` [none] * {blank} + Effects: :: A pointer to the value stored in the variant, if `v != nullptr && v\->index() == I`. Otherwise, `nullptr`. Remarks: :: These functions do not participate in overload resolution unless `I` < `sizeof...(T)`. ``` template constexpr add_pointer_t get_if(variant* v) noexcept; ``` ``` template constexpr add_pointer_t get_if(const variant* v) noexcept; ``` [none] * {blank} + Requires: :: The type `U` occurs exactly once in `T...`. Otherwise, the program is ill-formed. Effects: :: Equivalent to: `return get_if(v);` with `I` being the zero-based index of `U` in `T...`. ### unsafe_get (extension) ``` template constexpr variant_alternative_t>& unsafe_get(variant& v); ``` ``` template constexpr variant_alternative_t>&& unsafe_get(variant&& v); ``` ``` template constexpr const variant_alternative_t>& unsafe_get(const variant& v); ``` ``` template constexpr const variant_alternative_t>&& unsafe_get(const variant&& v); ``` [none] * {blank} + Requires: :: `v.index() == I`. Returns: :: a reference to the object stored in the variant. ### Relational Operators ``` template constexpr bool operator==(const variant& v, const variant& w); ``` [none] * {blank} + Returns: :: `v.index() == w.index() && get(v) == get(w)`, where `I` is `v.index()`. ``` template constexpr bool operator!=(const variant& v, const variant& w); ``` [none] * {blank} + Returns: :: `!(v == w)`. ``` template constexpr bool operator<(const variant& v, const variant& w); ``` [none] * {blank} + Returns: :: `v.index() < w.index() || (v.index() == w.index() && get(v) < get(w))`, where `I` is `v.index()`. ``` template constexpr bool operator>(const variant& v, const variant& w); ``` [none] * {blank} + Returns: :: `w < v`. ``` template constexpr bool operator<=(const variant& v, const variant& w); ``` [none] * {blank} + Returns: :: `v.index() < w.index() || (v.index() == w.index() && get(v) \<= get(w))`, where `I` is `v.index()`. ``` template constexpr bool operator>=(const variant& v, const variant& w); ``` [none] * {blank} + Returns: :: `w \<= v`. ### swap ``` template void swap(variant& v, variant& w) noexcept( /*see below*/ ); ``` [none] * {blank} + Effects: :: Equivalent to `v.swap(w)`. ### visit ``` template constexpr /*see below*/ visit(F&& f, V&&... v); ``` [none] * {blank} + Returns: :: `std::forward(f)(get(std::forward(v))...)`, where `I...` is `v.index()...`. Remarks: :: If `R` is given explicitly, as in `visit`, the return type is `R`. Otherwise, it's deduced from `F`. All possible applications of `F` to the variant alternatives must have the same return type for this deduction to succeed. ### visit_by_index (extension) ``` template constexpr /*see below*/ visit_by_index(V&& v, F&&.. f); ``` [none] * {blank} + Requires: :: `variant_size::value == sizeof...(F)`, or the program is ill-formed. Returns: :: `std::forward(fi)(get(std::forward(v)))`, where `i` is `v.index()` and `Fi` and `fi` are the `i`-th element of `F...` and `f...` accordingly. Remarks: :: If `R` is given explicitly, as in `visit_by_index`, the return type is `R`. Otherwise, it's deduced from `F...` and `V`. All the applications of `Fi` to the corresponding variant alternatives must have the same return type for this deduction to succeed. ### Stream Insertion (extension) ``` template std::basic_ostream& operator<<( std::basic_ostream& os, variant const& v ); ``` [none] * {blank} + Requires: :: `sizeof...(T) != 0`. Returns: :: `os << get(v)`, where `I` is `v.index()`. ``` template std::basic_ostream& operator<<( std::basic_ostream& os, monostate const& v ); ``` [none] * {blank} + Effects: :: `os << "monostate"`. Returns: :: `os`. ### bad_variant_access ``` class bad_variant_access: public std::exception { public: bad_variant_access() noexcept = default; char const * what() const noexcept { return "bad_variant_access"; } }; ``` ## This convenience header includes ``.