# std::optional<T>::optional

< cpp‎ | utility‎ | optional

constexpr optional() noexcept; constexpr optional( std::nullopt_t ) noexcept; | (1) | (C++17 起)
constexpr optional( const optional& other ); | (2) | (C++17 起)
constexpr optional( optional&& other ) noexcept(/* see below */); | (3) | (C++17 起)
| (4) |
template < class U > optional( const optional<U>& other ); |  | (C++17 起) (C++20 前) (条件性 `explicit`)
template < class U > constexpr optional( const optional<U>& other ); |  | (C++20 起) (条件性 `explicit`)
| (5) |
template < class U > optional( optional<U>&& other ); |  | (C++17 起) (C++20 前) (条件性 `explicit`)
template < class U > constexpr optional( optional<U>&& other ); |  | (C++20 起) (条件性 `explicit`)
template< class... Args > constexpr explicit optional( std::in_place_t, Args&&... args ); | (6) | (C++17 起)
template< class U, class... Args > constexpr explicit optional( std::in_place_t, std::initializer_list<U> ilist, Args&&... args ); | (7) | (C++17 起)
template < class U = T > constexpr optional( U&& value ); | (8) | (C++17 起) (条件性 `explicit`)

构造新的 `optional` 对象。

1) 构造不含值的对象。
2) 复制构造函数：若 `other` 含值，则初始化所含值，如同以表达式 *other 直接初始化（但不是直接列表初始化） `T` 类型对象。若 `other` 不含值，则构造一个不含值的对象。

- 若 std::is_copy_constructible_v<T> 为 false 则定义此构造函数为被删除。
- 若 std::is_trivially_copy_constructible_v<T> 为 true ，则它是平凡构造函数。

3) 移动构造函数：若 `other` 含值，则初始化所含值，如同以表达式 std::move(*other) 直接初始化（但不是直接列表初始化） `T` 类型对象，且不令 `other` 为空：被移动源的 `optional` 仍然含值，但该值自身是被移动的。

- 若 `other` 不含值，则构造一个不含值的对象。此构造函数不参与重载决议，除非 std::is_move_constructible_v<T> 为 true
- 。若 std::is_trivially_move_constructible_v<T> 为 true ，则它是平凡构造函数。

4) 转换复制构造函数：若 `other` 不含值，则构造不含值的 `optional` 对象。否则，构造含值的 `optional` 对象，如同以表达式 *other 直接初始化（但不是直接列表初始化） `T` 类型对象一般初始化。

- 此构造函数不参与重载决议，除非满足下列条件：
  - std::is_constructible_v<T, const U&> 为 true 。
  - `T` 不可从任何 std::optional<U> （可为 const ）类型表达式构造或转换，即下列 8 个类型特征均为 false ：
    - std::is_constructible_v<T, std::optional<U>&>
    - std::is_constructible_v<T, const std::optional<U>&>
    - std::is_constructible_v<T, std::optional<U>&&>
    - std::is_constructible_v<T, const std::optional<U>&&>
    - std::is_convertible_v<std::optional<U>&, T>
    - std::is_convertible_v<const std::optional<U>&, T>
    - std::is_convertible_v<std::optional<U>&&, T>
    - std::is_convertible_v<const std::optional<U>&&, T>
- 此构造函数为 explicit 若且唯若 std::is_convertible_v<const U&, T> 为 false 。

5) 转换移动构造函数：若 `other` 不含值，则构造不含值的 `optional` 对象。否则，构造含值的 `optional` 对象，如同以表达式 std::move(*other) 直接初始化（但不是直接列表初始化） `T` 类型对象一般初始化。

- 此构造函数不参与重载决议，除非满足下列条件：
  - std::is_constructible_v<T, U&&> 为 true 。
  - `T` 不可从任何std::optional<U> （可为 const ）类型表达式构造或转换，即下列 8 个类型特征均为 false ：
    - std::is_constructible_v<T, std::optional<U>&>
    - std::is_constructible_v<T, const std::optional<U>&>
    - std::is_constructible_v<T, std::optional<U>&&>
    - std::is_constructible_v<T, const std::optional<U>&&>
    - std::is_convertible_v<std::optional<U>&, T>
    - std::is_convertible_v<const std::optional<U>&, T>
    - std::is_convertible_v<std::optional<U>&&, T>
    - std::is_convertible_v<const std::optional<U>&&, T>
- 此构造函数为 explicit ，若且唯若 std::is_convertible_v<U&&, T> 为 false 。

6) 构造一个含值的对象，如同从参数 std::forward<Args>(args)... 直接初始化（但不是直接列表初始化） `T` 类型对象一般初始化。

- 若选择的 `T` 构造函数为 constexpr 构造函数，则此构造函数为 constexpr 构造函数。
- 该函数仅若 std::is_constructible_v<T, Args...> 为 true 才参与重载决议。

7) 构造一个含值的对象，如同从参数 ilist, std::forward<Args>(args)... 直接初始化（但不是直接列表初始化） `T` 类型对象一般初始化。

- 若选择的 `T` 构造函数为 constexpr 构造函数，则此构造函数为 constexpr 构造函数。
- 该函数仅若 std::is_constructible_v<T, std::initializer_list<U>&, Args&&...> 为 true 才参与重载决议。

8) 构造一个含值的对象，如同从参数 std::forward<U>(value) 直接初始化（但不是直接列表初始化） `T` 类型对象一般初始化。

- 若选择的 `T` 构造函数为 constexpr 构造函数，则此构造函数为 constexpr 构造函数。
- 此构造函数仅若 std::is_constructible_v<T, U&&> 为 true 且 std::decay_t<U> (C++20 前)std::remove_cvref_t<U> (C++20 起) 既非 std::in_place_t 亦非 std::optional<T> 才参与重载决议。
- 此构造函数为 explicit 若且唯若 std::is_convertible_v<U&&, T> 为 false 。

### 参数

other | - | 要复制其所含值的另一 `optional` 对象
value | - | 初始化所含值所用的值
args... | - | 初始化所含值所用的参数
ilist | - | 初始化所含值所用的 initializer_list

### 异常

2) 抛出任何 `T` 的构造函数所抛的异常。
3) 抛出任何 `T` 的构造函数所抛的异常。拥有下列
`noexcept` 说明：
noexcept(std::is_nothrow_move_constructible<T>::value)
4-8) 抛出任何 `T` 的构造函数所抛的异常。

### 示例

    #include <optional>
    #include <iostream>
    #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++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
P0602R4 | C++17 | 即使底层构造函数平凡，复制/移动构造函数亦可能不平凡 | 要求传播平凡性
P2231R1 | C++20 | 源自另一 `optional` 的转换构造函数不是 constexpr 而要求的操作在 C++20 中能是 | 使之为 constexpr

### 参阅

make_optional (C++17) | 创建一个 `optional` 对象 (函数模板)