std::variant<Types...>:: variant
|
constexpr
variant
(
)
noexcept
(
/* см. ниже */
)
;
|
(1) | (начиная с C++17) |
|
constexpr
variant
(
const
variant
&
other
)
;
|
(2) | (начиная с C++17) |
|
constexpr
variant
(
variant
&&
other
)
noexcept
(
/* см. ниже */
)
;
|
(3) | (начиная с C++17) |
|
template
<
class
T
>
constexpr variant ( T && t ) noexcept ( /* см. ниже */ ) ; |
(4) | (начиная с C++17) |
|
template
<
class
T,
class
...
Args
>
|
(5) | (начиная с C++17) |
|
template
<
class
T,
class
U,
|
(6) | (начиная с C++17) |
|
template
<
std::
size_t
I,
class
...
Args
>
|
(7) | (начиная с C++17) |
|
template
<
std::
size_t
I,
class
U,
|
(8) | (начиная с C++17) |
Создает новый объект
variant
.
-
Этот конструктор является
constexpr
тогда и только тогда, когда значение-инициализация альтернативного типа
T_0удовлетворяет требованиям для constexpr-функции . - Эта перегрузка участвует в разрешении перегрузки только если std:: is_default_constructible_v < T_0 > равно true .
variant
, содержащий ту же альтернативу, что и
other
, и
прямо инициализирует
содержащееся значение с помощью
*
std::
get_if
<
other.
index
(
)
>
(
std::
addressof
(
other
)
)
. В противном случае инициализирует
valueless_by_exception
вариант.
-
Этот конструктор определяется как удаленный, если только
std::
is_copy_constructible_v
<
T_i
>
не равно
true
для всех
T_iв Types... . -
Он является тривиальным, если
std::
is_trivially_copy_constructible_v
<
T_i
>
равно
true
для всех
T_iв Types... .
variant
, содержащий ту же альтернативу, что и
other
, и
прямо инициализирует
содержащееся значение с помощью
std
::
move
(
*
std::
get_if
<
other.
index
(
)
>
(
std::
addressof
(
other
)
)
)
. В противном случае инициализирует
valueless_by_exception
вариант.
-
Эта перегрузка участвует в разрешении перегрузки только если
std::
is_move_constructible_v
<
T_i
>
равно
true
для всех
T_iв Types... . -
Он является тривиальным, если
std::
is_trivially_move_constructible_v
<
T_i
>
равно
true
для всех
T_iв Types... .
T_j
, который был бы выбран разрешением перегрузки для выражения
F
(
std::
forward
<
T
>
(
t
)
)
, если бы существовала перегрузка воображаемой функции
F(T_i)
для каждого
T_i
в
Types...
, за исключением того, что сужающие преобразования не учитываются.
Формально:
-
-
Перегрузка
F
(
T_i
)
рассматривается только если объявление
T_i x
[
]
=
{
std::
forward
<
T
>
(
t
)
}
;
валидно для некоторой вымышленной переменной
x.
-
Перегрузка
F
(
T_i
)
рассматривается только если объявление
T_i 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 > равно true ,
- и выражение F ( std:: forward < T > ( t ) ) (где F - упомянутый выше набор воображаемых функций) корректно.
-
Этот конструктор является
constexpr
конструктором, если выбранный конструктор для
T_jявляется constexpr конструктором.
std::variant<std::string> v("abc"); // OK std::variant<std::string, std::string> w("abc"); // некорректно std::variant<std::string, const char*> x("abc"); // OK, выбирает const char* std::variant<std::string, bool> y("abc"); // OK, выбирает string; bool не является кандидатом std::variant<float, long, double> z = 0; // OK, содержит long // float и double не являются кандидатами
variant
с указанной альтернативой
T
и инициализирует содержащееся значение аргументами
std::
forward
<
Args
>
(
args
)
...
.
-
Если выбранный конструктор
Tявляется constexpr конструктором, этот конструктор также является constexpr конструктором. -
Эта перегрузка участвует в разрешении перегрузки только если
Tвстречается ровно один раз в Types... и std:: is_constructible_v < T, Args... > равно true .
variant
с указанной альтернативой
T
и инициализирует содержащееся значение аргументами
il,
std::
forward
<
Args
>
(
args
)
...
.
-
Если выбранный конструктор
Tявляется constexpr конструктором, этот конструктор также является constexpr конструктором. -
Эта перегрузка участвует в разрешении перегрузки только если
Tвстречается ровно один раз в Types... и std:: is_constructible_v < T, initializer_list < U > & , Args... > равно true .
variant
с альтернативой
T_i
, указанной индексом
I
, и инициализирует содержащееся значение аргументами
std::
forward
<
Args
>
(
args
)
...
.
-
Если выбранный конструктор
T_iявляется constexpr конструктором, этот конструктор также является constexpr конструктором. - Эта перегрузка участвует в разрешении перегрузки только если I < sizeof... ( Types ) и std:: is_constructible_v < T_i, Args... > равно true .
variant
с альтернативой
T_i
, заданной индексом
I
, и инициализирует содержащееся значение аргументами
il,
std::
forward
<
Args
>
(
args
)
...
.
-
Если выбранный конструктор
T_iявляется constexpr конструктором, этот конструктор также является constexpr конструктором. - Эта перегрузка участвует в разрешении перегрузки только если I < sizeof... ( Types ) и std:: is_constructible_v < T_i, std:: initializer_list < U > & , Args... > равно true .
Содержание |
Параметры
| other | - |
другой
variant
объект, значение которого нужно скопировать/переместить
|
| t | - | значение для инициализации содержащегося значения |
| args... | - | аргументы для инициализации содержащегося значения |
| il | - | список инициализации для инициализации содержащегося значения |
Исключения
T_i
в
Types...
.
T_i
в
Types...
.
T_j
.
Примечания
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 |