Namespaces
Variants

std::optional<T>:: optional

From cppreference.net
Utilities library
constexpr optional ( ) noexcept ;
(1) (自 C++17 起)
constexpr optional ( std:: nullopt_t ) noexcept ;
(2) (自 C++17 起)
constexpr optional ( const optional & other ) ;
(3) (自 C++17 起)
constexpr optional ( optional && other ) noexcept ( /* 见下文 */ ) ;
(4) (自 C++17 起)
template < class U >
optional ( const optional < U > & other ) ;
(5) (自 C++17 起)
(自 C++20 起为 constexpr)
(条件性显式)
template < class U >
optional ( optional < U > && other ) ;
(6) (自 C++17 起)
(自 C++20 起为 constexpr)
(条件性显式)
template < class ... Args >
constexpr explicit optional ( std:: in_place_t , Args && ... args ) ;
(7) (自 C++17 起)
template < class U, class ... Args >

constexpr explicit optional ( std:: in_place_t ,
std:: initializer_list < U > ilist,

Args && ... args ) ;
(8) (自 C++17 起)
template < class U = std:: remove_cv_t < T > >
constexpr optional ( U && value ) ;
(9) (自 C++17 起)
(条件性显式)

构造一个新的 optional 对象。

目录

参数

other - 另一个 optional 对象,其包含的值将被复制
value - 用于初始化所包含值的值
args... - 用于初始化所包含值的参数
ilist - 用于初始化所包含值的初始化列表

效果

重载版本 初始化方式 所含值的初始化器 构造后 has_value() 状态
( 1 ) 不适用 - false
( 2 )
( 3 ) 直接初始化 (非列表) * other other. has_value ( )
  • 若为 false ,则所含值未被初始化
( 4 ) std :: move ( * other )
( 5 ) * other
( 6 ) std :: move ( * other )
( 7 ) std:: forward < Args > ( args ) ... true
( 8 ) ilist, std:: forward < Args > ( args ) ...
( 9 ) std:: forward < U > ( value )

约束条件与补充信息

3) std:: is_copy_constructible_v < T > false ,则该构造函数被定义为已删除。
std:: is_trivially_copy_constructible_v < T > true ,则该构造函数是平凡的。
4) 此重载仅当 std:: is_move_constructible_v < T > true 时参与重载决议。
如果 std:: is_trivially_move_constructible_v < T > true ,则该构造函数是平凡的。
5) 此重载仅在满足以下所有条件时参与重载决议:
此重载的声明方式如同使用了 explicit ( ! std:: is_convertible_v < const U & , T > )
6) 此重载仅在满足以下所有条件时参与重载决议:
此重载的声明方式如同使用了 explicit ( ! std:: is_convertible_v < U, T > )
7) 此重载仅当 std:: is_constructible_v < T, Args... > true 时参与重载决议。
如果为初始化选择的 T 的构造函数是 constexpr 构造函数,则该构造函数也是 constexpr 构造函数。
8) 此重载仅当 std:: is_constructible_v < T, std:: initializer_list < U > & , Args... > true 时参与重载决议。
如果为初始化选择的 T 的构造函数是 constexpr 构造函数,则该构造函数也是 constexpr 构造函数。
9) 此重载仅在满足以下所有条件时参与重载决议:
此重载的声明方式如同使用了 explicit ( ! std:: is_convertible_v < U, T > )
如果为初始化选择的 T 的构造函数是 constexpr 构造函数,则该构造函数也是 constexpr 构造函数。
  1. 1.0 1.1 换言之, T 既不可构造也不可从任何类型为(可能 const 限定的) std:: optional < U > 的表达式转换而来

异常

3) 抛出 T 的构造函数抛出的任何异常。
4) 抛出 T 的构造函数抛出的任何异常。具有以下
noexcept 规范:
noexcept ( std:: is_nothrow_move_constructible < T > :: value )
5-9) 抛出由 T 的构造函数抛出的任何异常。

推导指引

注释

LWG 问题 3836 解决之前,从 std:: optional < U > 构造 std:: optional < bool > 时,若 U 不是 bool 类型,会选择重载 ( 9 ) 而非重载 ( 5,6 ) 。这是因为当 T (此处为 bool )可从 std:: optional < U > 构造或转换时,重载 ( 5,6 ) 不参与重载决议,而 std::optional::operator bool 使得这种转换对任意 U 皆成立。

因此,构造出的 std:: optional < bool > 始终包含一个值。该值的确定依据是提供的 std:: optional < U > 对象是否包含值,而非基于所含值直接初始化得到的 bool 值:

std::optional<bool> op_false(false);
std::optional<int> op_zero(0);
std::optional<int> from_bool(op_false); // 正确:包含值0(从false初始化)
std::optional<bool> from_int(op_zero);  // 缺陷(LWG 3836):包含true,因为
                                        // op_zero包含有效值,即使从该值
                                        // 初始化bool类型会得到false
功能测试 标准 功能特性
__cpp_lib_optional 202106L (C++20)
(DR20)
完全 constexpr ( 5,6 )

示例

#include <iostream>
#include <optional>
#include <string>
int main()
{
    std::optional<int> o1, // 空值
                       o2 = 1, // 从右值初始化
                       o3 = o2; // 拷贝构造函数
    // 调用 std::string( initializer_list<CharT> ) 构造函数
    std::optional<std::string> o4(std::in_place, {'a', 'b', 'c'});
    // 调用 std::string( size_type count, CharT ch ) 构造函数
    std::optional<std::string> o5(std::in_place, 3, 'A');
    // 使用推导指南从 std::string 移动构造
    std::optional o6(std::string{"deduction"});
    std::cout << *o2 << ' ' << *o3 << ' ' << *o4 << ' ' << *o5  << ' ' << *o6 << '\n';
}

输出:

1 1 abc AAA deduction

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 应用于 发布时的行为 正确行为
LWG 3836 C++17 当从 std:: optional < U > 构造 std:: optional < bool > 时,
U 不是 bool 则会选择重载 ( 9 )
在此情况下始终选择
转换复制/移动构造函数
LWG 3886 C++17 重载 ( 9 ) 的默认模板参数为 T 改为 std:: remove_cv_t < T >
P0602R4 C++17 即使底层构造函数是平凡的,
复制/移动构造函数也可能不是平凡的
要求传播
平凡性
P2231R1 C++20 来自其他 std::optional 的重载 ( 5,6 ) 不是 constexpr 改为 constexpr

参见

创建 optional 对象
(函数模板)