std::variant<Typen...>::variant
Aus de.cppreference.net
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
constexprgenau dann, wenn die Wertinitialisierung des AlternativtypsT_0die 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>trueist.
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>nichttruefür alleT_iinTypes...ist. - Er ist trivial, wenn
std::is_trivially_copy_constructible_v<T_i>truefür alleT_iinTypes...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>truefür alleT_iinTypes...ist. - Sie ist trivial, wenn
std::is_trivially_move_constructible_v<T_i>truefür alleT_iinTypes...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 DeklarationT_i x[] = { std::forward<T>(t) };für eine erfundene Variablexgültig ist.
- Eine Überladung
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 wievariantnoch 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>trueist,- 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 vonT_jein 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
Teinconstexpr-Konstruktor ist, ist dieser Konstruktor ebenfalls einconstexpr-Konstruktor. - Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn es genau ein Vorkommen von
TinTypes...gibt undstd::is_constructible_v<T, Args...>trueist.
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
Teinconstexpr-Konstruktor ist, ist dieser Konstruktor ebenfalls einconstexpr-Konstruktor. - Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn es genau ein Vorkommen von
TinTypes...gibt undstd::is_constructible_v<T, initializer_list<U>&, Args...>trueist.
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_ieinconstexpr-Konstruktor ist, ist dieser Konstruktor ebenfalls einconstexpr-Konstruktor. - Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn
I < sizeof...(Types)undstd::is_constructible_v<T_i, Args...>trueist.
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_ieinconstexpr-Konstruktor ist, ist dieser Konstruktor ebenfalls einconstexpr-Konstruktor. - Diese Überladung nimmt nur an der Überladungsauflösung teil, wenn
I < sizeof...(Types)undstd::is_constructible_v<T_i, std::initializer_list<U>&, Args...>trueist.
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:
noexcept
(
std::
is_nothrow_default_constructible_v
<
T_0
>
)
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
Diesen Code ausführen
#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 |