|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
variant::operator= | ||||
| Observers | ||||
| Modifiers | ||||
| Visitation | ||||
(C++26) | ||||
| Non-member functions | ||||
| Helper classes | ||||
| Helper objects | ||||
constexpr variant& operator=(const variant& rhs); | (1) | (since C++17) |
constexpr variant& operator=( variant&& rhs)noexcept(/* see below */); | (2) | (since C++17) |
template<class T> variant& operator=( T&& t)noexcept(/* see below */); | (3) | (since C++17) (constexpr since C++20) |
Assigns a new value to an existingvariant object.
valueless_by_exception if an exception is thrown on the copy-construction insideemplace.T_i inTypes.... This overload is trivial ifstd::is_trivially_copy_constructible_v<T_i>,std::is_trivially_copy_assignable_v<T_i> andstd::is_trivially_destructible_v<T_i> are alltrue for allT_i inTypes....j beingindex(). If an exception is thrown,*this does not become valueless: the value depends on the exception safety guarantee of the alternative's move assignment.T_i's move constructor,*this becomesvalueless_by_exception.T_i inTypes.... This overload is trivial ifstd::is_trivially_move_constructible_v<T_i>,std::is_trivially_move_assignable_v<T_i>, andstd::is_trivially_destructible_v<T_i> are alltrue for allT_i inTypes....T_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 everyT_i fromTypes... in scope at the same time, except that:x;T_j, assignsstd::forward<T>(t) to the value contained in*this. If an exception is thrown,*this does not become valueless: the value depends on the exception safety guarantee of the assignment called.valueless_by_exception if an exception is thrown on the initialization insideemplace.This overload participates in overload resolution only ifstd::decay_t<T>(until C++20)std::remove_cvref_t<T>(since C++20) is not the same type asvariant andstd::is_assignable_v<T_j&, T> istrue andstd::is_constructible_v<T_j, T> istrue and the expressionF(std::forward<T>(t)) (with F being the above-mentioned set of imaginary functions) is well formed.
std::variant<std::string> v1;v1="abc";// OKstd::variant<std::string,std::string> v2;v2="abc";// Errorstd::variant<std::string,bool> v3;v3="abc";// OK, chooses string; bool is not a candidatestd::variant<float,long,double> v4;// holds floatv4=0;// OK, holds long; float and double are not candidates
Contents |
| rhs | - | anothervariant |
| t | - | a value convertible to one of the variant's alternatives |
*this
| Feature-test macro | Value | Std | Feature |
|---|---|---|---|
__cpp_lib_variant | 202106L | (C++20) (DR) | Fullyconstexprstd::variant(3) |
#include <iomanip>#include <iostream>#include <string>#include <type_traits>#include <variant> std::ostream& operator<<(std::ostream& os,std::variant<int,std::string>const& va){ os<<": { "; std::visit([&](auto&& arg){using T=std::decay_t<decltype(arg)>;ifconstexpr(std::is_same_v<T,int>) os<< arg;elseifconstexpr(std::is_same_v<T,std::string>) os<<std::quoted(arg);}, va); return os<<" };\n";} int main(){std::variant<int,std::string> a{2017}, b{"CppCon"};std::cout<<"a"<< a<<"b"<< b<<'\n'; std::cout<<"(1) operator=( const variant& rhs )\n"; a= b;std::cout<<"a"<< a<<"b"<< b<<'\n'; std::cout<<"(2) operator=( variant&& rhs )\n"; a= std::move(b);std::cout<<"a"<< a<<"b"<< b<<'\n'; std::cout<<"(3) operator=( T&& t ), where T is int\n"; a=2019;std::cout<<"a"<< a<<'\n'; std::cout<<"(3) operator=( T&& t ), where T is std::string\n";std::string s{"CppNow"};std::cout<<"s: "<<std::quoted(s)<<'\n'; a= std::move(s);std::cout<<"a"<< a<<"s: "<<std::quoted(s)<<'\n';}
Possible output:
a: { 2017 };b: { "CppCon" }; (1) operator=( const variant& rhs )a: { "CppCon" };b: { "CppCon" }; (2) operator=( variant&& rhs )a: { "CppCon" };b: { "" }; (3) operator=( T&& t ), where T is inta: { 2019 }; (3) operator=( T&& t ), where T is std::strings: "CppNow"a: { "CppNow" };s: ""The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 3024 | C++17 | copy assignment operator doesn't participate in overload resolution if any member type is not copyable | defined as deleted instead |
| LWG 3585 | C++17 | converting assignment was sometimes unexpectedly ill-formed because there was no available move assignment | made well-formed |
| P0602R4 | C++17 | copy/move assignment may not be trivial even if underlying operations are trivial | required to propagate triviality |
| P0608R3 | C++17 | converting assignment blindly assembles an overload set, leading to unintended conversions | narrowing and boolean conversions not considered |
| P2231R1 | C++20 | converting assignment(3) was notconstexpr while the required operations can beconstexpr in C++20 | madeconstexpr |
constructs a value in thevariant, in place(public member function)[edit] |