std::variant<Types...>::variant
С сайта ru.cppreference.net
constexpr variant() noexcept(/* see below */);
|
(1) | (начиная с C++17) |
constexpr variant( const variant& other );
|
(2) | (начиная с C++17) |
constexpr variant( variant&& other ) noexcept(/* see below */);
|
(3) | (начиная с C++17) |
template< class T >
constexpr variant( T&& t ) noexcept(/* see below */);
|
(4) | (начиная с C++17) |
template< class T,
class... Args >
constexpr explicit variant( std::in_place_type_t<T>,
Args&&... args );
|
(5) | (начиная с 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) | (начиная с C++17) |
template< std::size_t I,
class... Args >
constexpr explicit variant( std::in_place_index_t<I>,
Args&&... args );
|
(7) | (начиная с 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) | (начиная с C++17) |
Конструирует новый объект variant.
1) Конструктор по умолчанию. Конструирует
variant, содержащий значение-инициализированное значение первой альтернативы (index() равен нулю).
- Этот конструктор является
constexprтогда и только тогда, когда инициализация значением типа альтернативыT_0удовлетворяла бы требованиям для constexpr-функции. - Эта перегрузка участвует в разрешении перегрузки только если
std::is_default_constructible_v<T_0>являетсяtrue.
2) Конструктор копирования. Если
other не является valueless_by_exception, конструирует variant, содержащий ту же альтернативу, что и other, и прямо инициализирует содержащееся значение с помощью *std::get_if<other.index()>(std::addressof(other)). В противном случае инициализирует valueless_by_exception variant.
- Этот конструктор определяется как удалённый, если только
std::is_copy_constructible_v<T_i>не являетсяtrueдля всехT_iизTypes.... - Он тривиален, если
std::is_trivially_copy_constructible_v<T_i>являетсяtrueдля всехT_iизTypes....
3) Конструктор перемещения. Если
other не является valueless_by_exception, конструирует variant, содержащий ту же альтернативу, что и other, и прямо инициализирует содержащееся значение с помощью std::move(*std::get_if<other.index()>(std::addressof(other))). В противном случае инициализирует valueless_by_exception variant.
- Эта перегрузка участвует в разрешении перегрузки только если
std::is_move_constructible_v<T_i>являетсяtrueдля всехT_iизTypes.... - Она тривиальна, если
std::is_trivially_move_constructible_v<T_i>являетсяtrueдля всехT_iизTypes....
4) Преобразующий конструктор. Конструирует
variant, содержащий тип альтернативы T_j, который был бы выбран разрешением перегрузки для выражения F(std::forward<T>(t)), если бы существовала перегрузка воображаемой функции F(T_i) для каждого T_i из Types..., за исключением того, что сужающие преобразования не рассматриваются.
Формально:
- Перегрузка
F(T_i)рассматривается только в том случае, если объявлениеT_i x[] = { std::forward<T>(t) };корректно для некоторой изобретённой переменнойx.
- Перегрузка
Прямо инициализирует содержащееся значение как при прямой несписочной инициализации из
std::forward<T>(t).
- Эта перегрузка участвует в разрешении перегрузки только если
sizeof...(Types) > 0,std::decay_t<T>(до C++20)std::remove_cvref_t<T>(начиная с C++20) не является ни тем же типом, что иvariant, ни специализацией std::in_place_type_t, ни специализацией std::in_place_index_t,std::is_constructible_v<T_j, T>T_itrueявляется- ,и выражение
F(std::forward<T>(t))(где F — указанный выше набор воображаемых функций) корректно.
- Этот конструктор является
constexprконструктором, если выбранный конструкторT_j's является constexpr-конструктором.
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) Конструирует
variant с указанной альтернативой T и инициализирует содержащееся значение аргументами std::forward<Args>(args)....
- Если выбранный конструктор
T's являетсяconstexprконструктором, этот конструктор также являетсяconstexprконструктором. - Эта перегрузка участвует в разрешении перегрузки только если существует ровно одно вхождение
TвTypes...иstd::is_constructible_v<T, Args...>являетсяtrue.
6) Конструирует
variant с указанной альтернативой T и инициализирует содержащееся значение аргументами il, std::forward<Args>(args)....
- Если выбранный конструктор
T's являетсяconstexprконструктором, этот конструктор также являетсяconstexprконструктором. - Эта перегрузка участвует в разрешении перегрузки только если существует ровно одно вхождение
TвTypes...иstd::is_constructible_v<T, initializer_list<U>&, Args...>являетсяtrue.
7) Конструирует
variant с альтернативой T_i, указанной индексом I, и инициализирует содержащееся значение аргументами std::forward<Args>(args)....
- Если выбранный конструктор
T_i's являетсяconstexprконструктором, этот конструктор также являетсяconstexprконструктором. - Эта перегрузка участвует в разрешении перегрузки только если
I < sizeof...(Types)иstd::is_constructible_v<T_i, Args...>являетсяtrue.
8) Конструирует
variant с альтернативой T_i, указанной индексом I, и инициализирует содержащееся значение аргументами il, std::forward<Args>(args)....
- Если выбранный конструктор
T_i's являетсяconstexprконструктором, этот конструктор также являетсяconstexprконструктором. - Эта перегрузка участвует в разрешении перегрузки только если
I < sizeof...(Types)иstd::is_constructible_v<T_i, std::initializer_list<U>&, Args...>являетсяtrue.
Параметры
| other | - |
другой
variant
объект, значение которого нужно скопировать/переместить
|
| t | - | значение для инициализации содержащегося значения |
| args... | - | аргументы для инициализации содержащегося значения |
| il | - | список инициализации для инициализации содержащегося значения |
Исключения
1)
Может выбрасывать любое исключение, вызванное инициализацией значения первой альтернативы.
noexcept
спецификация:
noexcept
(
std::
is_nothrow_default_constructible_v
<
T_0
>
)
2)
Может выбросить любое исключение, выбрасываемое при прямой инициализации любого
T_i
в
Types...
.
3)
Может выбрасывать любое исключение, выбрасываемое при move-конструировании любого
T_i
в
Types...
.
noexcept
спецификация:
noexcept
(
(
std::
is_nothrow_move_constructible_v
<
Types
>
&&
...
)
)
4)
Может выбрасывать любое исключение, выброшенное при инициализации выбранной альтернативы
T_j
.
noexcept
спецификация:
noexcept
(
std::
is_nothrow_constructible_v
<
T_j, T
>
)
5-8)
Может выбросить любое исключение, выбрасываемое при вызове выбранного конструктора выбранной альтернативы.
Примечания
MSVC STL изначально рассматривал P0608R3 как изменение в C++20. Начиная с VS 2022 17.12, MSVC STL также рассматривает P0608R3 как отчёт о дефекте для C++17.
Пример
Запустить этот код
#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-инициализирует первую альтернативу std::variant<int, std::string> var0; assert(std::holds_alternative<int>(var0) and var0.index() == 0 and std::get<int>(var0) == 0); // инициализирует первую альтернативу с std::string{"STR"}; std::variant<std::string, int> var1{"СТРОКА"}; assert(var1.index() == 0); std::cout << "1) " << std::get<std::string>(var1) << '\n'; // инициализирует вторую альтернативу значением int == 42; std::variant<std::string, int> var2{42}; assert(std::holds_alternative<int>(var2)); std::cout << "2) " << std::get<int>(var2) << '\n'; // инициализирует первую альтернативу с 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'; // инициализирует вторую альтернативу с 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'; // инициализирует первую альтернативу с помощью std::string{"ABCDE", 3}; std::variant<std::string, vector_t, bool> var5 {std::in_place_index<0>, "ABCDE", 3}; assert(var5.индекс() == 0); std::cout << "5) " << std::get<std::string>(var5) << '\n'; // инициализирует вторую альтернативу с 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'; }
Вывод:
1) STR
2) 42
3) AAAA
4) { 1 2 3 4 5 }
5) ABC
6) { 42 42 42 42 }
` сохранен без изменений, так как содержит код и числовые значения, которые не подлежат переводу в соответствии с вашими требованиями. HTML-разметка и атрибуты также сохранены в оригинальном виде.
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены ретроактивно к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение в опубликованной версии | Корректное поведение |
|---|---|---|---|
| LWG 2901 | C++17 |
Предоставлены конструкторы с поддержкой аллокаторов, но
variant
не может корректно поддерживать аллокаторы
|
конструкторы удалены |
| P0739R0 | C++17 |
шаблон конструктора преобразования плохо взаимодействует
с выводом аргументов шаблона класса |
добавлено ограничение |
| LWG 3024 | C++17 |
конструктор копирования не участвует в
разрешении перегрузки, если любой тип элемента не копируемый |
определен как удаленный вместо этого |
| P0602R4 | C++17 |
конструкторы копирования/перемещения могут не быть
тривиальными, даже если базовые конструкторы тривиальны |
требуется распространять тривиальность |
| P0608R3 | C++17 |
конструктор преобразования слепо собирает
набор перегрузок, приводя к непреднамеренным преобразованиям |
сужающие и булевы преобразования не рассматриваются |
| P1957R2 | C++17 |
конструктор преобразования для
bool
не позволял
неявное преобразование |
Преобразование указателя в
bool
является сужающим и
конструктор преобразования не имеет исключения для bool |