std::expected
出自 cppreference.com
| 定義於標頭 <expected> |
||
| template< class T, class E > class expected; |
(1) | (自 C++23 起) |
| template< class T, class E > requires std::is_void_v<T> |
(2) | (自 C++23 起) |
類別模板 std::expected 提供了一種表示兩種值之一的方法:型別為 T 的預期(expected)值,或型別為 E 的非預期(unexpected)值。expected 永遠不會處於無值狀態。
2) void 部分特化。表示預期的 void 值或包含一個非預期值。若它包含一個非預期值,該值會嵌套於
expected 物件之中。若程式將 expected 具現化為參考型別、函式型別,或 std::unexpected 的特化,則該程式為格式錯誤(ill-formed)。此外,T 不得為 std::in_place_t 或 std::unexpect_t。
目錄 |
[編輯] 模板參數
| T | - | 預期值的型別。該型別必須是(可包含 cv 限定符的) void,或是符合 可解構(Destructible) 需求(特別是不允許陣列和參考型別)。 |
| E | - | 非預期值的型別。該型別必須符合 可解構(Destructible) 需求,且必須是 std::unexpected 的合法模板引數(特別是不允許陣列、非物件型別和 cv 限定型別)。 |
[編輯] 成員型別
| 成員型別 | 定義 |
value_type
|
T
|
error_type
|
E
|
unexpected_type
|
std::unexpected<E>
|
[編輯] 成員別名模板
| 類型 | 定義 |
| rebind<U> | std::expected<U, error_type> |
[編輯] 資料成員
| 成員 | 定義 |
bool has_val |
expected 物件目前是否表示預期值(僅用於闡述的成員物件*) |
T val (僅限主模板) |
預期值 (僅供說明之變體成員物件*) |
E unex |
非預期值 (僅供說明之變體成員物件*) |
[編輯] 成員函式
建構 expected 物件(公開成員函式) | |
解構 expected 物件及其包含的值(公開成員函式) | |
| 賦值內容 (公開成員函式) | |
觀察器 | |
| 存取預期值 (公開成員函式) | |
| 檢查物件是否包含預期值 (公開成員函式) | |
| 傳回預期值 (公開成員函式) | |
| 傳回非預期值 (公開成員函式) | |
| 若存在則傳回預期值,否則傳回另一個值 (公開成員函式) | |
| 若存在則傳回非預期值,否則傳回另一個值 (公開成員函式) | |
單子 (Monadic) 操作 | |
若存在預期值,則傳回將給定函式應用於該值的結果;否則,傳回 expected 本身(公開成員函式) | |
若存在預期值,則傳回包含轉換後預期值的 expected;否則,傳回 expected 本身(公開成員函式) | |
若包含預期值則傳回 expected 本身;否則,傳回將給定函式應用於非預期值的結果(公開成員函式) | |
若包含預期值則傳回 expected 本身;否則,傳回包含轉換後非預期值的 expected(公開成員函式) | |
修改器 | |
| 原地(in-place)建構預期值 (公開成員函式) | |
| 交換內容 (公開成員函式) | |
[編輯] 非成員函式
| (C++23) |
比較 expected 物件(函式模板) |
| (C++23) |
特化 std::swap 演算法 (函式) |
[編輯] 輔助類別
| (C++23) |
表示為意外值 (類別範本) |
| (C++23) |
當對包含非預期值的 expected 進行檢查存取時所拋出的例外(類別模板) |
| (C++23) |
expected 中意外值的就地建構標籤(標籤) |
[編輯] 附註
具有相同功能的型別在 Rust 中稱為 Result,在 Haskell 中稱為 Either。
| 功能測試巨集 | 數值 | 標準 | 功能 |
|---|---|---|---|
__cpp_lib_expected |
202202L |
(C++23) | 類別模板 std::expected 與相關輔助類別 |
202211L |
(C++23) | 用於 std::expected 的單子(Monadic)函式 |
[編輯] 範例
執行此程式碼
#include <cmath> #include <expected> #include <iomanip> #include <iostream> #include <string_view> enum class parse_error { invalid_input, overflow }; auto parse_number(std::string_view& str) -> std::expected<double, parse_error> { const char* begin = str.data(); char* end; double retval = std::strtod(begin, &end); if (begin == end) return std::unexpected(parse_error::invalid_input); else if (std::isinf(retval)) return std::unexpected(parse_error::overflow); str.remove_prefix(end - begin); return retval; } int main() { auto process = [](std::string_view str) { std::cout << "str: " << std::quoted(str) << ", "; if (const auto num = parse_number(str); num.has_value()) std::cout << "value: " << *num << '\n'; // If num did not have a value, dereferencing num // would cause an undefined behavior, and // num.value() would throw std::bad_expected_access. // num.value_or(123) uses specified default value 123. else if (num.error() == parse_error::invalid_input) std::cout << "error: invalid input\n"; else if (num.error() == parse_error::overflow) std::cout << "error: overflow\n"; else std::cout << "unexpected!\n"; // or invoke std::unreachable(); }; for (auto src : {"42", "42abc", "meow", "inf"}) process(src); }
輸出
str: "42", value: 42 str: "42abc", value: 42 str: "meow", error: invalid input str: "inf", error: overflow
[編輯] 瑕疵報告
下列更改行為的缺陷報告追溯應用於之前的 C++ 標準。
| DR | 應用於 | 出版時的行為 | 正確的行為 |
|---|---|---|---|
| LWG 4141 | C++23 | 儲存需求 配置 (allocation) 描述易造成混淆 |
所包含的物件必須 嵌套於 expected 物件內 |
[編輯] 參考資料
- C++23 標準 (ISO/IEC 14882:2024)
- 22.8 Expected 物件 [expected]
[編輯] 參見
| (C++17) |
一種型別安全的識別聯合體 (discriminated union) (類別模板) |
| (C++17) |
一個可能持有也可能不持有物件的封裝器 (類別模板) |