Namespaces
Variants

std::variant<Typen...>::variant

Aus de.cppreference.net
 
 
Dienstprogrammbibliothek
Sprachunterstützung
Typunterstützung (grundlegende Typen, 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
Relationsoperatoren (veraltet in C++20)
Ganzzahlvergleichsfunktionen
(C++20)(C++20)(C++20)    
(C++20)
Swap und Typoperationen
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
Allgemeine Vokabeltypen
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)



 
 
constexpr variant() noexcept(/* see below */);
(1) (seit C++17)
constexpr variant( const variant& other );
(2) (seit C++17)
constexpr variant( variant&& other ) noexcept(/* see below */);
(3) (seit C++17)
template< class T >
constexpr variant( T&& t ) noexcept(/* see below */);
(4) (seit C++17)
template< class T,
          class... Args >
constexpr explicit variant( std::in_place_type_t<T>,
                            Args&&... args );
(5) (seit C++17)
template< class T,
          class U,
          class... Args >
constexpr explicit variant( std::in_place_type_t<T>,
                            std::initializer_list<U> il,
                            Args&&... args );
(6) (seit C++17)
template< std::size_t I,
          class... Args >
constexpr explicit variant( std::in_place_index_t<I>,
                            Args&&... args );
(7) (seit C++17)
template< std::size_t I,
          class U,
          class... Args >
constexpr explicit variant( std::in_place_index_t<I>,
                            std::initializer_list<U> il,
                            Args&&... args );
(8) (seit C++17)

Erzeugt ein neues variant-Objekt.

1) Standardkonstruktor. Erzeugt ein variant, das den wertinitialisierten Wert der ersten Alternative hält (index() ist null).
  • Dieser Konstruktor ist constexpr genau dann, wenn die Wertinitialisierung des Alternativtyps T_0 die Anforderungen für eine constexpr-Funktion erfüllen würde.
  • Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn std::is_default_constructible_v<T_0> true ist.
2) Kopierkonstruktor. Wenn other nicht valueless_by_exception ist, erzeugt es ein variant, das dieselbe Alternative wie other hält und direktinitialisiert den enthaltenen Wert mit *std::get_if<other.index()>(std::addressof(other)). Andernfalls initialisiert es eine valueless_by_exception-Variante.
  • Dieser Konstruktor ist als gelöscht definiert, sofern std::is_copy_constructible_v<T_i> nicht true für alle T_i in Types... ist.
  • Er ist trivial, wenn std::is_trivially_copy_constructible_v<T_i> true für alle T_i in Types... ist.
3) Verschiebekonstruktor. Wenn other nicht valueless_by_exception ist, erzeugt es ein variant, das dieselbe Alternative wie other hält und direktinitialisiert den enthaltenen Wert mit std::move(*std::get_if<other.index()>(std::addressof(other))). Andernfalls initialisiert es eine valueless_by_exception-Variante.
  • Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn std::is_move_constructible_v<T_i> true für alle T_i in Types... ist.
  • Sie ist trivial, wenn std::is_trivially_move_constructible_v<T_i> true für alle T_i in Types... ist.
4) Konvertierungskonstruktor. Erzeugt ein variant, das den Alternativtyp T_j hält, der durch Überladungsauflösung für den Ausdruck F(std::forward<T>(t)) ausgewählt würde, wenn es eine Überladung einer imaginären Funktion F(T_i) für jedes T_i in Types... gäbe, außer dass einschränkende Konvertierungen nicht berücksichtigt werden.

Formal:

  • 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.
Direktinitialisiert den enthaltenen Wert wie durch direkte Nicht-Listeninitialisierung von std::forward<T>(t).
  • Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn
    • sizeof...(Types) > 0,
    • std::decay_t<T>(bis C++20)std::remove_cvref_t<T>(seit C++20) weder derselbe Typ wie variant noch eine Spezialisierung von std::in_place_type_t noch eine Spezialisierung von std::in_place_index_t ist,
    • 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.
  • Dieser Konstruktor ist ein constexpr-Konstruktor, wenn der ausgewählte Konstruktor von T_j ein constexpr-Konstruktor ist.
std::variant<std::string> v("abc"); // OK
std::variant<std::string, std::string> w("abc"); // ill-formed
std::variant<std::string, const char*> x("abc"); // OK, chooses const char*
std::variant<std::string, bool> y("abc"); // OK, chooses string; bool is not a candidate
std::variant<float, long, double> z = 0; // OK, holds long
                                         // float and double are not candidates
5) Erzeugt ein variant mit der angegebenen Alternative T und initialisiert den enthaltenen Wert mit den Argumenten std::forward<Args>(args)....
  • Wenn der ausgewählte Konstruktor von T ein constexpr-Konstruktor ist, ist dieser Konstruktor ebenfalls ein constexpr-Konstruktor.
  • Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn es genau ein Vorkommen von T in Types... gibt und std::is_constructible_v<T, Args...> true ist.
6) Erzeugt ein variant mit der angegebenen Alternative T und initialisiert den enthaltenen Wert mit den Argumenten il, std::forward<Args>(args)....
  • Wenn der ausgewählte Konstruktor von T ein constexpr-Konstruktor ist, ist dieser Konstruktor ebenfalls ein constexpr-Konstruktor.
  • Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn es genau ein Vorkommen von T in Types... gibt und std::is_constructible_v<T, initializer_list<U>&, Args...> true ist.
7) Erzeugt ein variant mit der Alternative T_i, die durch den Index I angegeben wird, und initialisiert den enthaltenen Wert mit den Argumenten std::forward<Args>(args)....
  • Wenn der ausgewählte Konstruktor von T_i ein constexpr-Konstruktor ist, ist dieser Konstruktor ebenfalls ein constexpr-Konstruktor.
  • Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn I < sizeof...(Types) und std::is_constructible_v<T_i, Args...> true ist.
8) Erzeugt ein variant mit der Alternative T_i, die durch den Index I angegeben wird, und initialisiert den enthaltenen Wert mit den Argumenten il, std::forward<Args>(args)....
  • Wenn der ausgewählte Konstruktor von T_i ein constexpr-Konstruktor ist, ist dieser Konstruktor ebenfalls ein constexpr-Konstruktor.
  • Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn I < sizeof...(Types) und std::is_constructible_v<T_i, std::initializer_list<U>&, Args...> true ist.

Parameter

other - ein weiteres variant Objekt, dessen enthaltenen Wert kopiert/verschoben werden soll
t - Wert zur Initialisierung des enthaltenen Werts
args... - Argumente zur Initialisierung des enthaltenen Werts
il - Initialisierungsliste zur Initialisierung des enthaltenen Werts

Exceptions

1) Kann jede Ausnahme werfen, die durch die Wertinitialisierung der ersten Alternative ausgelöst wird.
noexcept Spezifikation:
2) Kann jede Ausnahme werfen, die durch die Direktinitialisierung eines beliebigen T_i in Types... ausgelöst wird.
3) Kann jede Ausnahme werfen, die durch Move-Konstruktion eines beliebigen T_i in Types... ausgelöst wird.
noexcept Spezifikation:
noexcept ( ( std:: is_nothrow_move_constructible_v < Types > && ... ) )
4) Kann jede Ausnahme werfen, die durch die Initialisierung der ausgewählten Alternative T_j ausgelöst wird.
noexcept Spezifikation:
noexcept ( std:: is_nothrow_constructible_v < T_j, T > )
5-8) Kann jede Ausnahme werfen, die durch den Aufruf des ausgewählten Konstruktors der ausgewählten Alternative ausgelöst wird.

Hinweise

MSVC STL behandelte ursprünglich P0608R3 als Änderung in C++20. Ab VS 2022 17.12 behandelt MSVC STL P0608R3 auch als Defect Report gegen C++17.

Beispiel

#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-initialisiert erste Alternative
    std::variant<int, std::string> var0;
    assert(std::holds_alternative<int>(var0) and
           var0.index() == 0 and
           std::get<int>(var0) == 0);
    // initialisiert erste Alternative mit std::string{"STR"};
    std::variant<std::string, int> var1{"STR"};
    assert(var1.index() == 0);
    std::cout << "1) " << std::get<std::string>(var1) << '\n';
    // initialisiert zweite Alternative mit int == 42;
    std::variant<std::string, int> var2{42};
    assert(std::holds_alternative<int>(var2));
    std::cout << "2) " << std::get<int>(var2) << '\n';
    // initialisiert erste Alternative mit 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';
    // initialisiert die zweite Alternative mit 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';
    // initialisiert erste Alternative mit 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';
    // initialisiert zweite Alternative mit 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';
}

Ausgabe:

1) STR
2) 42
3) AAAA
4) { 1 2 3 4 5 }
5) ABC
6) { 42 42 42 42 }

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
LWG 2901 C++17 Allokator-bewusste Konstruktoren bereitgestellt, aber
variant kann Allokatoren nicht ordnungsgemäß unterstützen
Konstruktoren entfernt
P0739R0 C++17 Konvertierungskonstruktor-Template interagiert
schlecht mit Klassen-Template-Argumentableitung
Einschränkung hinzugefügt
LWG 3024 C++17 Kopierkonstruktor nimmt nicht an der
Überladungsauflösung teil, wenn ein Mitgliedstyp nicht kopierbar ist
Stattdessen als gelöscht definiert
P0602R4 C++17 Kopier-/Verschiebekonstruktoren können nicht
trivial sein, selbst wenn zugrunde liegende Konstruktoren trivial sind
Muss Trivialität weitergeben
P0608R3 C++17 Konvertierungskonstruktor stellt blind
einen Überladungssatz zusammen, was zu unbeabsichtigten Konvertierungen führt
Einschränkende und boolesche Konvertierungen nicht berücksichtigt
P1957R2 C++17 Konvertierungskonstruktor für bool erlaubte keine
implizite Konvertierung
Zeiger-zu- bool Konvertierung ist einschränkend und
Konvertierungskonstruktor hat keine
Ausnahme für bool