Namespaces
Variants

std::variant<Types...>::operator=

Von de.cppreference.net
 
 
Dienstprogrammbibliothek
Sprachunterstützung
Typunterstützung (Basistypen, RTTI)
Bibliotheks-Feature-Test-Makros (C++20)
Programm-Dienstprogramme
Variadische Funktionen
Koroutinen-Unterstützung (C++20)
Vertragsunterstützung (C++26)
Drei-Wege-Vergleich
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Allgemeine Dienstprogramme
Relationale Operatoren (veraltet in C++20)
Ganzzahl-Vergleichsfunktionen
(C++20)(C++20)(C++20)    
(C++20)
Tausch- und Typoperationen
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Allgemeine Vokabular-Typen
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)



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

Weist einem vorhandenen variant-Objekt einen neuen Wert zu.

1) Kopierzuweisung:
  • Falls sowohl *this als auch rhs ausnahmsweise wertlos sind, wird nichts unternommen.
  • Andernfalls, wenn rhs wertlos ist, *this jedoch nicht, wird der in *this enthaltene Wert zerstört und es wird wertlos gemacht.
  • Andernfalls, wenn rhs dieselbe Alternative wie *this enthält, wird der in rhs enthaltene Wert dem in *this enthaltenen Wert zugewiesen. Wenn eine Ausnahme ausgelöst wird, wird *this nicht wertlos: Der Wert hängt von der Ausnahmesicherheitsgarantie der Kopierzuweisung der Alternative ab.
  • Andernfalls, wenn die von rhs gehaltene Alternative entweder nothrow-kopierkonstruierbar ist oder nicht nothrow-verschiebekonstruierbar 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_exception werden, wenn beim Kopierkonstruktor innerhalb von emplace eine Ausnahme ausgelöst wird.
  • Andernfalls äquivalent zu this->operator=(variant(rhs)).
Diese Überladung ist als gelöscht definiert, es sei denn, std::is_copy_constructible_v<T_i> und std::is_copy_assignable_v<T_i> sind beide true für alle 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.
2) Verschiebezuweisung:
  • Falls sowohl *this als auch rhs ausnahmsweise wertlos sind, wird nichts unternommen.
  • Andernfalls, wenn rhs wertlos ist, *this jedoch nicht, wird der in *this enthaltene Wert zerstört und es wird wertlos gemacht.
  • Andernfalls, wenn rhs dieselbe Alternative wie *this enthält, wird std::move(*std::get_if<j>(std::addressof(rhs))) dem in *this enthaltenen Wert zugewiesen, wobei j index() ist. Wenn eine Ausnahme ausgelöst wird, wird *this nicht wertlos: Der Wert hängt von der Ausnahmesicherheitsgarantie der Verschiebezuweisung der Alternative ab.
  • Andernfalls (wenn rhs und *this unterschiedliche Alternativen enthalten) äquivalent zu this->emplace<rhs.index()>(std::move(*std::get_if<rhs.index()>(std::addressof(rhs)))). Wenn eine Ausnahme durch den Verschiebekonstruktor von T_i ausgelöst wird, wird *this valueless_by_exception.
Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn std::is_move_constructible_v<T_i> und std::is_move_assignable_v<T_i> beide true für alle 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.
3) Konvertierungszuweisung.
  • Bestimmt den Alternativtyp T_j, der durch Überladungsauflösung für den Ausdruck F(std::forward<T>(t)) ausgewählt würde, gäbe es gleichzeitig eine Überladung einer imaginären Funktion F(T_i) für jedes T_i aus Types... im Gültigkeitsbereich, 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 x gültig ist;
  • Wenn *this bereits ein T_j enthält, wird std::forward<T>(t) dem in *this enthaltenen Wert zugewiesen. Wenn eine Ausnahme ausgelöst wird, wird *this nicht wertlos: Der Wert hängt von der Ausnahmesicherheitsgarantie der aufgerufenen Zuweisung ab.
  • Andernfalls, wenn std::is_nothrow_constructible_v<T_j, T> || !std::is_nothrow_move_constructible_v<T_j> true ist, äquivalent zu this->emplace<j>(std::forward<T>(t)). *this kann valueless_by_exception werden, wenn bei der Initialisierung innerhalb von emplace eine Ausnahme ausgelöst wird.
  • Andernfalls äquivalent zu this->emplace<j>(T_j(std::forward<T>(t))).

Diese Überladung nimmt nur 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"; // 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

Parameter

rhs - another variant
t - ein in eine der Varianten-Alternativen konvertierbarer Wert

Rückgabewert

* this

Exceptions

1) Kann jede Ausnahme werfen, die durch Zuweisung und Kopier-/Verschiebeinitialisierung einer beliebigen Alternative ausgelöst wird.
2)
noexcept Spezifikation:
noexcept ( ( ( std:: is_nothrow_move_constructible_v < Types > &&
std:: is_nothrow_move_assignable_v < Types > ) && ... ) )
3)
noexcept Spezifikation:

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)