std::optional<T>::optional
來自 cppreference.com
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(/* see below */); |
(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, |
(8) | (C++17 起) |
template< class U = std::remove_cv_t<T> > constexpr optional( U&& value ); |
(9) | (C++17 起) (條件式顯式) |
構造新的 optional
物件。
目錄 |
[編輯] 引數
其他 | - | 另一個 optional 物件,其包含值被複制 |
value | - | 用於初始化包含值的值 |
args... | - | 用於初始化包含值的引數 |
ilist | - | 用於初始化包含值的初始化列表 |
[編輯] 效果
過載 | 初始化方法 | 包含值的初始化器 | 構造後 has_value() |
---|---|---|---|
(1) | N/A | - | false |
(2) | |||
(3) | 直接 (非列表) | *other | other.has_value()
|
(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) |
[編輯] 約束和補充資訊
如果 std::is_trivially_copy_constructible_v<T> 為 true,則此建構函式是平凡的。
如果 std::is_trivially_move_constructible_v<T> 為 true,則此建構函式是平凡的。
5) 僅當以下所有條件都滿足時,此過載才參與過載決議
- std::is_constructible_v<T, const U&> 為 true。
- 如果
T
不是(可能帶 cv 限定符的)bool,則以下 8 個值均為 false[1]- 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>)。
6) 僅當以下所有條件都滿足時,此過載才參與過載決議
- std::is_constructible_v<T, U> 為 true。
- 如果
T
不是(可能帶 cv 限定符的)bool,則以下 8 個值均為 false[1]- 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>)。
如果為初始化選擇的
T
的建構函式是 constexpr 建構函式,則此建構函式也是 constexpr 建構函式。 如果為初始化選擇的
T
的建構函式是 constexpr 建構函式,則此建構函式也是 constexpr 建構函式。9) 僅當以下所有條件都滿足時,此過載才參與過載決議
- 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>。
- 如果
T
是(可能帶 cv 限定符的)bool,則 std::decay_t<U>(C++20 前)std::remove_cvref_t<U>(C++20 起) 不是std::optional
的特化。
此過載的宣告方式,就好像其帶有 explicit(!std::is_convertible_v<U, T>)。
如果為初始化選擇的
T
的建構函式是 constexpr 建構函式,則此建構函式也是 constexpr 建構函式。- ↑ 1.0 1.1 換句話說,
T
既不能從型別為(可能帶 const 限定符的)std::optional<U> 的任何表示式構造,也不能從其轉換。
[編輯] 異常
3) 丟擲
T
的建構函式丟擲的任何異常。5-9) 丟擲
T
的建構函式丟擲的任何異常。[編輯] 推導指南
[編輯] 註記
在解決 LWG issue 3836 之前,從 std::optional<U> 構造 std::optional<bool> 會選擇過載 (9) 而不是過載 (5,6),如果 U
不是 bool。這是因為如果 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); // OK: contains 0 (initialized from false) std::optional<bool> from_int(op_zero); // DEFECT (LWG 3836): contains true because // op_zero contains a value, even if initializing // bool from that value gives false
特性測試宏 | 值 | 標準 | 特性 |
---|---|---|---|
__cpp_lib_optional |
202106L |
(C++20) (DR20) |
完全 constexpr (5,6) |
[編輯] 示例
執行此程式碼
#include <iostream> #include <optional> #include <string> int main() { std::optional<int> o1, // empty o2 = 1, // init from rvalue o3 = o2; // copy-constructor // calls std::string( initializer_list<CharT> ) constructor std::optional<std::string> o4(std::in_place, {'a', 'b', 'c'}); // calls std::string( size_type count, CharT ch ) constructor std::optional<std::string> o5(std::in_place, 3, 'A'); // Move-constructed from std::string using deduction guide to pick the type 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)過載決議 會選擇過載 (9) 如果 U 不是 bool |
在這種情況下 總是選擇轉換 複製/移動建構函式 |
LWG 3886 | C++17 | 過載 (9) 的預設模板引數是 T |
改為 std::remove_cv_t<T> |
P0602R4 | C++17 | 複製/移動建構函式可能不是平凡的 即使底層建構函式是平凡的 |
要求 傳播平凡性 |
P2231R1 | C++20 | 來自另一個 std::optional 的過載 (5,6) 不是 constexpr |
設為 constexpr |
[編輯] 參閱
(C++17) |
建立 optional 物件(函式模板) |