std::variant<Types...>:: operator=
|
constexpr
variant
&
operator
=
(
const
variant
&
rhs
)
;
|
(1) | (seit C++17) |
|
constexpr
variant
&
operator
=
(
variant
&&
rhs
)
noexcept
(
/* siehe unten */
)
;
|
(2) | (seit C++17) |
|
template
<
class
T
>
variant & operator = ( T && t ) noexcept ( /* siehe unten */ ) ; |
(3) |
(seit C++17)
(constexpr seit C++20) |
Weist einem bestehenden
variant
-Objekt einen neuen Wert zu.
- Wenn sowohl * this als auch rhs wertlos durch Exception sind, tut nichts.
- Andernfalls, wenn rhs wertlos ist, aber * this nicht, zerstört den enthaltenen Wert in * this und macht ihn wertlos.
- Andernfalls, wenn rhs die gleiche Alternative enthält wie * this , weist den in rhs enthaltenen Wert dem in * this enthaltenen Wert zu. Wenn eine Exception ausgelöst wird, wird * this nicht wertlos: der Wert hängt von der Exception-Sicherheitsgarantie der Copy-Zuweisung der Alternative ab.
-
Andernfalls, wenn die von
rhs
gehaltene Alternative entweder nothrow copy-konstruierbar oder
nicht
nothrow move-konstruierbar ist (bestimmt durch
std::is_nothrow_copy_constructible
bzw.
std::is_nothrow_move_constructible
), äquivalent zu
this
-
>
emplace
<
rhs.
index
(
)
>
(
*
std::
get_if
<
rhs.
index
(
)
>
(
std::
addressof
(
rhs
)
)
)
.
*
this
kann
valueless_by_exceptionwerden, wenn eine Exception bei der Copy-Konstruktion innerhalb vonemplaceausgelöst wird. - Andernfalls äquivalent zu this - > operator = ( variant ( rhs ) ) .
T_i
in
Types...
. Diese Überladung ist trivial, wenn
std::
is_trivially_copy_constructible_v
<
T_i
>
,
std::
is_trivially_copy_assignable_v
<
T_i
>
und
std::
is_trivially_destructible_v
<
T_i
>
alle
true
für alle
T_i
in
Types...
sind.
- Wenn sowohl * this als auch rhs wertlos durch Exception sind, tut nichts.
- Andernfalls, wenn rhs wertlos ist, aber * this nicht, zerstört den in * this enthaltenen Wert und macht ihn wertlos.
-
Andernfalls, wenn
rhs
dieselbe Alternative wie
*
this
enthält, weist
std
::
move
(
*
std::
get_if
<
j
>
(
std::
addressof
(
rhs
)
)
)
dem in
*
this
enthaltenen Wert zu, wobei
jgleichindex()ist. Wenn eine Exception ausgelöst wird, wird * this nicht wertlos: Der Wert hängt von der Exception-Sicherheitsgarantie der Move-Zuweisung der Alternative ab. -
Andernfalls (wenn
rhs
und
*
this
verschiedene Alternativen enthalten), äquivalent zu
this
-
>
emplace
<
rhs.
index
(
)
>
(
std
::
move
(
*
std::
get_if
<
rhs.
index
(
)
>
(
std::
addressof
(
rhs
)
)
)
)
. Wenn eine Exception durch den Move-Konstruktor von
T_iausgelöst wird, wird * this zuvalueless_by_exception.
T_i
in
Types...
sind. Diese Überladung ist trivial, wenn
std::
is_trivially_move_constructible_v
<
T_i
>
,
std::
is_trivially_move_assignable_v
<
T_i
>
und
std::
is_trivially_destructible_v
<
T_i
>
alle
true
für alle
T_i
in
Types...
sind.
-
Bestimmt den alternativen Typ
T_jder durch Überladungsauflösung für den Ausdruck F ( std:: forward < T > ( t ) ) ausgewählt würde, wenn es gleichzeitig Überladungen einer imaginären Funktion F ( T_i ) für jedenT_iausTypes...im Gültigkeitsbereich gäbe, mit der Ausnahme, dass:
-
-
Eine Überladung
F
(
T_i
)
wird nur berücksichtigt, wenn die Deklaration
T_i x
[
]
=
{
std::
forward
<
T
>
(
t
)
}
;
für eine erfundene Variable
xgültig ist;
-
Eine Überladung
F
(
T_i
)
wird nur berücksichtigt, wenn die Deklaration
T_i x
[
]
=
{
std::
forward
<
T
>
(
t
)
}
;
für eine erfundene Variable
-
Falls
*
this
bereits einen
T_jenthält, weist std:: forward < T > ( t ) dem enthaltenen Wert in * this zu. Falls eine Exception ausgelöst wird, wird * this nicht wertlos: Der Wert hängt von der Exception-Sicherheitsgarantie der aufgerufenen Zuweisung ab. -
Andernfalls, falls
std::
is_nothrow_constructible_v
<
T_j, T
>
||
!
std::
is_nothrow_move_constructible_v
<
T_j
>
gleich
true
ist, entspricht dies
this
-
>
emplace
<
j
>
(
std::
forward
<
T
>
(
t
)
)
.
*
this
kann
valueless_by_exceptionwerden, falls eine Exception bei der Initialisierung innerhalb vonemplaceausgelöst wird. - Andernfalls entspricht dies this - > emplace < j > ( T_j ( std:: forward < T > ( t ) ) ) .
Diese Überladung nimmt nur dann an der Überladungsauflösung teil, wenn
std::
decay_t
<
T
>
(bis C++20)
std::
remove_cvref_t
<
T
>
(seit C++20)
nicht derselbe Typ wie
variant
ist und
std::
is_assignable_v
<
T_j
&
, T
>
true
ist und
std::
is_constructible_v
<
T_j, T
>
true
ist und der Ausdruck
F
(
std::
forward
<
T
>
(
t
)
)
(wobei F die oben erwähnte Menge imaginärer Funktionen ist) wohlgeformt ist.
std::variant<std::string> v1; v1 = "abc"; // OK std::variant<std::string, std::string> v2; v2 = "abc"; // Fehler std::variant <std::string, bool> v3; v3 = "abc"; // OK, wählt string; bool ist kein Kandidat std::variant<float, long, double> v4; // enthält float v4 = 0; // OK, enthält long; float und double sind keine Kandidaten
Inhaltsverzeichnis |
Parameter
| rhs | - |
another
variant
|
| t | - | ein in eine der Varianten-Alternativen konvertierbarer Wert |
Rückgabewert
* this
Exceptions
std:: is_nothrow_move_assignable_v < Types > ) && ... ) )
std:: is_nothrow_constructible_v < T_j, T > )
Hinweise
| Feature-Test Makro | Wert | Std | Funktion |
|---|---|---|---|
__cpp_lib_variant
|
202106L
|
(C++20)
(DR) |
Vollständig
constexpr
std::variant
(
3
)
|
Beispiel
#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'; }
Mögliche Ausgabe:
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: ""
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| LWG 3024 | C++17 |
Copy-Zuweisungsoperator nimmt nicht an der Überladungsauflösung teil
falls ein Mitgliedstyp nicht kopierbar ist |
stattdessen als gelöscht definiert |
| LWG 3585 | C++17 |
Konvertierungszuweisung war manchmal unerwartet ungültig
da keine Move-Zuweisung verfügbar war |
als gültig gemacht |
| P0602R4 | C++17 |
Copy-/Move-Zuweisung könnte nicht trivial sein
selbst wenn zugrundeliegende Operationen trivial sind |
muss Trivialität propagieren |
| P0608R3 | C++17 |
Konvertierungszuweisung stellt blind einen Überladungssatz zusammen,
was zu unbeabsichtigten Konvertierungen führt |
Einschränkende und boolesche Konvertierungen
werden nicht berücksichtigt |
| P2231R1 | C++20 |
Konvertierungszuweisung
(
3
)
war nicht
constexpr
obwohl die erforderlichen Operationen in C++20 constexpr sein können |
als constexpr gemacht |
Siehe auch
Konstruiert einen Wert im
variant
, direkt vor Ort
(öffentliche Member-Funktion) |