GSP
Quick Navigator

Search Site

Unix VPS
A - Starter
B - Basic
C - Preferred
D - Commercial
MPS - Dedicated
Previous VPSs
* Sign Up! *

Support
Contact Us
Online Help
Handbooks
Domain Status
Man Pages

FAQ
Virtual Servers
Pricing
Billing
Technical

Network
Facilities
Connectivity
Topology Map

Miscellaneous
Server Agreement
Year 2038
Credits
 

USA Flag

 

 

Man Pages
std::variant::operator=(3) C++ Standard Libary std::variant::operator=(3)

std::variant::operator= - std::variant::operator=


constexpr variant& operator=( const variant& rhs ); (1) (since C++17)
constexpr variant& operator=( variant&& rhs ) (2) (since C++17)
noexcept(/* see below */);
template< class T > (since C++17)
variant& operator=( T&& t ) noexcept(/* see below (until C++20)
*/); (3)
template< class T >
constexpr variant& operator=( T&& t ) noexcept(/* (since C++20)
see below */);


Assigns a new value to an existing variant object.


1) Copy-assignment:


* If both *this and rhs are valueless by exception, does nothing.
* Otherwise, if rhs is valueless, but *this is not, destroys the value contained
in *this and makes it valueless.
* Otherwise, if rhs holds the same alternative as *this, assigns the value
contained in rhs 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 alternative's copy assignment.
* Otherwise, if the alternative held by rhs is either nothrow copy constructible
or not nothrow move constructible (as determined by
std::is_nothrow_copy_constructible and std::is_nothrow_move_constructible,
respectively), equivalent to this->emplace<rhs.index()>(get<rhs.index()>(rhs)).
*this may become valueless_by_exception if an exception is thrown on the
copy-construction inside emplace.
* Otherwise, equivalent to this->operator=(variant(rhs)).


This overload is defined as deleted unless std::is_copy_constructible_v<T_i> and
std::is_copy_assignable_v<T_i> are both true for all T_i in Types.... This overload
is trivial if
std::is_trivially_copy_constructible_v<T_i>,std::is_trivially_copy_assignable_v<T_i>
and std::is_trivially_destructible_v<T_i> are all true for all T_i in Types....
2) Move-assignment:


* If both *this and rhs are valueless by exception, does nothing
* Otherwise, if rhs is valueless, but *this is not, destroys the value contained
in *this and makes it valueless
* Otherwise, if rhs holds the same alternative as *this, assigns
std::get<j>(std::move(rhs)) to the value contained in *this, with j being
index(). If an exception is thrown, *this does not become valueless: the value
depends on the exception safety guarantee of the alternative's move assignment.
* Otherwise (if rhs and *this hold different alternatives), equivalent to
this->emplace<rhs.index()>(get<rhs.index()>(std::move(rhs))). If an exception is
thrown by T_i's move constructor, *this becomes valueless_by_exception.


This overload participates in overload resolution only if
std::is_move_constructible_v<T_i> and std::is_move_assignable_v<T_i> are both true
for all T_i in Types.... This overload is trivial if
std::is_trivially_move_constructible_v<T_i>,
std::is_trivially_move_assignable_v<T_i>, and std::is_trivially_destructible_v<T_i>
are all true for all T_i in Types....
3) Converting assignment.


* Determines the alternative type T_j that would be selected by overload
resolution for the expression F(std::forward<T>(t)) if there was an overload of
imaginary function F(T_i) for every T_i from Types... in scope at the same time,
except that:


* An overload F(T_i) is only considered if the declaration T_i x[] = {
std::forward<T>(t) }; is valid for some invented variable x;


* If *this already holds a T_j, assigns std::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.
* Otherwise, if std::is_nothrow_constructible_v<T_j, T> ||
!std::is_nothrow_move_constructible_v<T_j> is true, equivalent to
this->emplace<j>(std::forward<T>(t)). *this may become valueless_by_exception if
an exception is thrown on the initialization inside emplace.
* Otherwise, equivalent to this->emplace<j>(T_j(std::forward<T>(t))).


This overload participates in overload resolution only if
std::decay_t<T>
(until C++20)
std::remove_cvref_t<T>
(since C++20) is not the same type as variant and std::is_assignable_v<T_j&, T> is
true and std::is_constructible_v<T_j, T> is true and the expression
F(std::forward<T>(t)) (with F being the above-mentioned set of imaginary functions)
is well formed.


std::variant<std::string> v1;
v1 = "abc"; // OK
std::variant<std::string, std::string> v2;
v2 = "abc"; // Error
std::variant <std::string, bool> v3;
v3 = "abc"; // OK, chooses string; bool is not a candidate
std::variant<float, long, double> v4; //holds float
v4 = 0; // OK, holds long; float and double are not candidates


rhs - another variant
t - a value convertible to one of the variant's alternatives


*this


1) May throw any exception thrown by assignment and copy/move initialization of any
alternative.
2)
noexcept specification:
noexcept(((std::is_nothrow_move_constructible_v<Types> &&
std::is_nothrow_move_assignable_v<Types>) && ...))
3)
noexcept specification:
noexcept(std::is_nothrow_assignable_v<T_j&, T> &&
std::is_nothrow_constructible_v<T_j, T>)

// Run this code


#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)>;
if constexpr (std::is_same_v<T, int>)
os << arg;
else if constexpr (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';
}


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 int
a: { 2019 };


(3) operator=( T&& t ), where T is std::string
s: "CppNow"
a: { "CppNow" };
s: ""


Defect reports


The following behavior-changing defect reports were applied retroactively to
previously published C++ standards.


DR Applied to Behavior as published Correct behavior
copy assignment operator doesn't
LWG 3024 C++17 participate in overload resolution defined as deleted instead
if any member type is not copyable
copy/move assignment may not be
P0602R4 C++17 trivial required to propagate
even if underlying operations are triviality
trivial
converting assignment blindly narrowing and boolean
P0608R3 C++17 assembles an overload set, conversions
leading to unintended conversions not considered
converting assignment was not
P2231R1 C++20 constexpr made constexpr
while the required operations can be
in C++20
converting assignment was sometimes
LWG 3585 C++17 unexpectedly ill-formed made well-formed
because there was no available move
assignment


emplace constructs a value in the variant, in place
(public member function)

2022.07.31 http://cppreference.com

Search for    or go to Top of page |  Section 3 |  Main Index

Powered by GSP Visit the GSP FreeBSD Man Page Interface.
Output converted with ManDoc.