std::variant<Types...>::variant

来自cppreference.com
< cpp‎ | utility‎ | variant
 
 
工具库
通用工具
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)
(C++20)
swap 与类型运算
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
常用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)

初等字符串转换
(C++17)
(C++17)
栈踪
 
 
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() 为零)。
2) 复制构造函数。若 other因异常无值,则构造一个保有与 other 相同可选项的 variant ,并以 std::get<other.index()>(other) 直接初始化所含值。否则,初始化一个因异常无值variant
3) 移动构造函数。若 other因异常无值,则构造一个保有与 other 相同可选项的 variant 并以 std::get<other.index()>(std::move(other)) 直接初始化所含值。否则,初始化一个因异常无值variant
4) 转换构造函数。构造保有会被重载决议对表达式 F(std::forward<T>(t)) 选择的可选项 T_j ,假设对来自 Types... 中的每个 T_i 同时存在一个虚构函数 F(T_i) 的重载,除了:
  • 仅若声明 T_i x[] = { std::forward<T>(t) }; 对某个虚设变量 x 才考虑 F(T_i)
  • T_i 是(可有 cv 限定的) bool ,则仅若 std::decay_t<T> (C++20 前)std::remove_cvref_t<T> (C++20 起) 亦为 bool 才考虑 F(T_i)
如同用直接非列表初始化从 std::forward<T>(t) 直接初始化所含值。
  • 此重载仅若
  • T_j 的被选择构造函数为 constexpr 构造函数,则此构造函数为 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 不是候选
5) 构造一个有指定可选项类型 Tvariant 并以参数 std::forward<Args>(args)... 初始化所含值。
  • T 的被选择构造函数是 constexpr 构造函数,则此构造函数亦为 constexpr 构造函数。
  • 此重载仅若 Types... 中正好出现一次 Tstd::is_constructible_v<T, Args...>true 才参与重载决议。
6) 构造一个有指定可选项类型 Tvariant 并以参数 il, std::forward<Args>(args)... 初始化所含值。
  • T 的被选择构造函数是 constexpr 构造函数,则此构造函数亦为 constexpr 构造函数。
  • 此重载仅若 Types... 中正好出现一次 Tstd::is_constructible_v<T, initializer_list<U>&, Args...>true 才参与重载决议。
7) 构造一个有下标 I 所指定的可选项类型 {{tt|T_i} }的 variant 并以参数std::forward<Args>(args)... 初始化所含值。
  • T_i 的被选择构造函数是 constexpr 构造函数,则此构造函数亦为 constexpr 构造函数。
  • 此重载仅若 I < sizeof...(Types)std::is_constructible_v<T_i, Args...> 皆为 true 才参与重载决议。
8) 构造一个有下标 I 所指定的可选项类型 T_ivariant 并以参数 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 - 用以初始化被所含值的初始化器列表
a - 传递给被所含值的分配器

异常

1) 可能抛出首个可选项的值初始化所抛的任何异常。
2) 可能抛出直接初始化任何 Types... 中的 T_i 所抛的任何异常。
3) 可能抛出移动构造任何 Types... 中的 T_i 所抛的任何异常。
noexcept 说明:  
noexcept( (std::is_nothrow_move_constructible_v<Types> && ...))
4) 可能抛出初始化所选可选项T_j所抛的任何异常。
noexcept 说明:  
5-8) 可能抛出调用所选可选项的所选构造函数所抛的任何异常。

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR 应用于 出版时的行为 正确行为
LWG 2901 C++17 提供具分配器构造函数但 variant 不能正确支持分配器 移除构造函数
P0739R0 C++17 转换构造函数模板与类模板实参推导交互困难 添加了制约
LWG 3024 C++17 若任何成员类型非可复制,则复制构造函数不参与重载决议 改为定义为被删除
P0602R4 C++17 即使底层构造函数平凡,复制/移动构造函数亦可为非平凡 要求传播平凡性
P0608R3 C++17 转换构造函数盲目地组成重载集,导致不想要的转换 不考虑窄化与布尔转换

示例