|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
variant::variant | ||||
| Observers | ||||
| Modifiers | ||||
| Visitation | ||||
(C++26) | ||||
| Non-member functions | ||||
| Helper classes | ||||
| Helper objects | ||||
constexpr variant()noexcept(/* see below */); | (1) | (since C++17) |
constexpr variant(const variant& other); | (2) | (since C++17) |
constexpr variant( variant&& other)noexcept(/* see below */); | (3) | (since C++17) |
template<class T> constexpr variant( T&& t)noexcept(/* see below */); | (4) | (since C++17) |
template<class T, class...Args> | (5) | (since C++17) |
template<class T, class U, | (6) | (since C++17) |
template<std::size_t I, class...Args> | (7) | (since C++17) |
template<std::size_t I, class U, | (8) | (since C++17) |
Constructs a newvariant object.
variant holding thevalue-initialized value of the first alternative (index() is zero).T_0 would satisfy the requirements for aconstexpr function.variant holding the same alternative asother anddirect-initializes the contained value with*std::get_if<other.index()>(std::addressof(other)). Otherwise, initializes avalueless_by_exception variant.T_i inTypes....T_i inTypes....variant holding the same alternative asother anddirect-initializes the contained value withstd::move(*std::get_if<other.index()>(std::addressof(other))). Otherwise, initializes avalueless_by_exception variant.T_i inTypes....T_i inTypes....variant holding the alternative typeT_j that would be selected by overload resolution for the expressionF(std::forward<T>(t)) if there was an overload of imaginary functionF(T_i) for eachT_i inTypes..., except that narrowing conversions aren't considered.Formally:
x.variant, nor a specialization ofstd::in_place_type_t, nor a specialization ofstd::in_place_index_t,T_j's selected constructor is a constexpr constructor.std::variant<std::string> v("abc");// OKstd::variant<std::string,std::string> w("abc");// ill-formedstd::variant<std::string,constchar*> x("abc");// OK, chooses const char*std::variant<std::string,bool> y("abc");// OK, chooses string; bool is not a candidatestd::variant<float,long,double> z=0;// OK, holds long// float and double are not candidates
variant with the specified alternativeT and initializes the contained value with the argumentsstd::forward<Args>(args)....T's selected constructor is aconstexpr constructor, this constructor is also aconstexpr constructor.T inTypes... andstd::is_constructible_v<T, Args...> istrue.variant with the specified alternativeT and initializes the contained value with the argumentsil,std::forward<Args>(args)....T's selected constructor is aconstexpr constructor, this constructor is also aconstexpr constructor.T inTypes... andstd::is_constructible_v<T, initializer_list<U>&, Args...> istrue.variant with the alternativeT_i specified by the indexI and initializes the contained value with the argumentsstd::forward<Args>(args)....T_i's selected constructor is aconstexpr constructor, this constructor is also aconstexpr constructor.variant with the alternativeT_i specified by the indexI and initializes the contained value with the argumentsil,std::forward<Args>(args)....T_i's selected constructor is aconstexpr constructor, this constructor is also aconstexpr constructor.Contents |
| other | - | anothervariant object whose contained value to copy/move |
| t | - | value to initialize the contained value with |
| args... | - | arguments to initialize the contained value with |
| il | - | initializer list to initialize the contained value with |
T_i inTypes....T_i inTypes....T_j.MSVC STL initially treatedP0608R3 as a change in C++20. As of VS 2022 17.12, MSVC STL also treats P0608R3 as a defect report against C++17.
#include <cassert>#include <iostream>#include <string>#include <variant>#include <vector> using vector_t=std::vector<int>; auto& operator<<(auto& out,const vector_t& v){ out<<"{ ";for(int e: v) out<< e<<' ';return out<<'}';} int main(){// value-initializes first alternativestd::variant<int,std::string> var0;assert(std::holds_alternative<int>(var0) and var0.index()==0 and std::get<int>(var0)==0); // initializes first alternative with std::string{"STR"};std::variant<std::string,int> var1{"STR"};assert(var1.index()==0);std::cout<<"1) "<< std::get<std::string>(var1)<<'\n'; // initializes second alternative with int == 42;std::variant<std::string,int> var2{42};assert(std::holds_alternative<int>(var2));std::cout<<"2) "<< std::get<int>(var2)<<'\n'; // initializes first alternative with std::string{4, 'A'};std::variant<std::string, vector_t,float> var3{std::in_place_type<std::string>,4,'A'};assert(var3.index()==0);std::cout<<"3) "<< std::get<std::string>(var3)<<'\n'; // initializes second alternative with std::vector{1,2,3,4,5};std::variant<std::string, vector_t,char> var4{std::in_place_type<vector_t>,{1,2,3,4,5}};assert(var4.index()==1);std::cout<<"4) "<< std::get<vector_t>(var4)<<'\n'; // initializes first alternative with std::string{"ABCDE", 3};std::variant<std::string, vector_t,bool> var5{std::in_place_index<0>,"ABCDE",3};assert(var5.index()==0);std::cout<<"5) "<< std::get<std::string>(var5)<<'\n'; // initializes second alternative with std::vector(4, 42);std::variant<std::string, vector_t,char> var6{std::in_place_index<1>,4,42};assert(std::holds_alternative<vector_t>(var6));std::cout<<"6) "<< std::get<vector_t>(var6)<<'\n';}
Output:
1) STR2) 423) AAAA4) { 1 2 3 4 5 }5) ABC6) { 42 42 42 42 }The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 2901 | C++17 | allocator-aware constructors provided butvariant can't properly support allocators | constructors removed |
| P0739R0 | C++17 | converting constructor template interacts poorly with class template argument deduction | constraint added |
| LWG 3024 | C++17 | copy constructor doesn't participate in overload resolution if any member type is not copyable | defined as deleted instead |
| P0602R4 | C++17 | copy/move constructors may not be trivial even if underlying constructors are trivial | required to propagate triviality |
| P0608R3 | C++17 | converting constructor blindly assembles an overload set, leading to unintended conversions | narrowing and boolean conversions not considered |
| P1957R2 | C++17 | converting constructor forbool did not allow implicit conversion | Pointer tobool conversion is narrowing and converting constructor has no exception forbool |