命名空間
變體
動作

std::expected

出自 cppreference.com
< cpp‎ | 工具
 
 
 
 
定義於標頭 <expected>
template< class T, class E >
class expected;
(1) (自 C++23 起)
template< class T, class E >

    requires std::is_void_v<T>

class expected<T, E>;
(2) (自 C++23 起)

類別模板 std::expected 提供了一種表示兩種值之一的方法:型別為 T預期(expected)值,或型別為 E非預期(unexpected)值。expected 永遠不會處於無值狀態。

1) 主模板。將預期值或非預期值儲存在其自身的儲存空間內,該空間嵌套於 expected 物件之中。
2) void 部分特化。表示預期的 void 值或包含一個非預期值。若它包含一個非預期值,該值會嵌套於 expected 物件之中。

若程式將 expected 具現化為參考型別、函式型別,或 std::unexpected 的特化,則該程式為格式錯誤(ill-formed)。此外,T 不得為 std::in_place_tstd::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)建構預期值
(公開成員函式) [編輯]
交換內容
(公開成員函式) [編輯]

[編輯] 非成員函式

比較 expected 物件
(函式模板) [編輯]
特化 std::swap 演算法
(函式) [編輯]

[編輯] 輔助類別

表示為意外值
(類別範本) [編輯]
當對包含非預期值的 expected 進行檢查存取時所拋出的例外
(類別模板) [編輯]
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)
一個可能持有也可能不持有物件的封裝器
(類別模板) [編輯]
English Deutsch 日本語 中文(简体) 中文(繁體)