Skip to content

std::expected 实现分析

std::expected 是 C++23 引入的错误处理容器,类似 Rust 的 Result 类型。本文基于 GCC 和 LLVM 的源码,分析 expected 的内部实现。


一、核心概念

1.1 什么是 expected

expected 表示一个可能包含值或错误的容器:

cpp
// expected 的基本使用
expected<int, error_code> divide(int a, int b) {
    if (b == 0) return unexpected(error_code::divide_by_zero);
    return a / b;
}

auto result = divide(10, 2);
if (result) {
    cout << *result << endl;  // 5
} else {
    cout << "Error: " << result.error() << endl;
}

二、核心数据结构

2.1 存储布局

expected 的内存布局:

┌─────────────────────────────────────┐
│ bool has_value_                      │  ← 是否有值
├─────────────────────────────────────┤
│ 存储空间                             │
│   ┌─────────────────────────────┐   │
│   │ T value 或 E error          │   │
│   └─────────────────────────────┘   │
└─────────────────────────────────────┘

2.2 GCC (libstdc++) 的实现(源码分析)

cpp
// 源码路径:references/impl/gcc/libstdc++-v3/include/std/expected

// bad_expected_access 异常类
template<typename _Er>
class bad_expected_access : public bad_expected_access<void> {
public:
    explicit bad_expected_access(_Er __e) : _M_unex(std::move(__e)) { }
    
    // 获取错误值
    _Er& error() & noexcept { return _M_unex; }
    const _Er& error() const & noexcept { return _M_unex; }
    _Er&& error() && noexcept { return std::move(_M_unex); }
    
private:
    _Er _M_unex;  // 存储错误值
};

// unexpected 标签类型
struct unexpect_t {
    explicit unexpect_t() = default;
};
inline constexpr unexpect_t unexpect{};

// unexpected 包装器
template<typename _Er>
class unexpected {
    _Er _M_unex;
public:
    unexpected(const unexpected&) = default;
    unexpected(unexpected&&) = default;
    
    template<typename _Err = _Er>
    explicit unexpected(_Err&& __e) : _M_unex(std::forward<_Err>(__e)) { }
    
    const _Er& error() const& noexcept { return _M_unex; }
    _Er& error() & noexcept { return _M_unex; }
};

// expected 的基本实现
template<typename _Tp, typename _Er>
class expected {
    bool _M_has_value;
    union {
        aligned_storage_t<sizeof(_Tp), alignof(_Tp)> _M_val;
        aligned_storage_t<sizeof(_Er), alignof(_Er)> _M_err;
    };
    
public:
    // 构造函数
    constexpr expected() : _M_has_value(true) {
        ::new (&_M_val) _Tp();
    }
    
    constexpr expected(const expected& __rhs) : _M_has_value(__rhs._M_has_value) {
        if (_M_has_value) {
            ::new (&_M_val) _Tp(__rhs._M_get_val());
        } else {
            ::new (&_M_err) _Er(__rhs._M_get_err());
        }
    }
    
    // 预期值构造函数
    template<typename _Up = _Tp>
    constexpr expected(_Up&& __u) : _M_has_value(true) {
        ::new (&_M_val) _Tp(std::forward<_Up>(__u));
    }
    
    // 意外值构造函数
    template<typename _Err = _Er>
    constexpr expected(unexpected<_Err>&& __e) : _M_has_value(false) {
        ::new (&_M_err) _Er(std::move(__e).error());
    }
    
    // 析构函数
    ~expected() {
        if (_M_has_value) {
            _M_get_val().~_Tp();
        } else {
            _M_get_err().~_Er();
        }
    }
    
    // 检查是否有值
    constexpr bool has_value() const noexcept { return _M_has_value; }
    constexpr explicit operator bool() const noexcept { return _M_has_value; }
    
    // 获取值
    constexpr _Tp& operator*() & { return _M_get_val(); }
    constexpr const _Tp& operator*() const& { return _M_get_val(); }
    constexpr _Tp&& operator*() && { return std::move(_M_get_val()); }
    
    // 获取错误
    constexpr const _Er& error() const& { return _M_get_err(); }
    constexpr _Er& error() & { return _M_get_err(); }
    
    // value_or
    constexpr _Tp value_or(const _Tp& __default) const& {
        return _M_has_value ? _M_get_val() : __default;
    }
    
    // transform
    template<typename _Fn>
    constexpr auto transform(_Fn&& __fn) -> expected<decltype(__fn(declval<_Tp>())), _Er> {
        if (_M_has_value) {
            return expected<decltype(__fn(declval<_Tp>())), _Er>(
                std::forward<_Fn>(__fn)(_M_get_val()));
        }
        return unexpected<(_Er)>(_M_get_err());
    }
    
private:
    _Tp& _M_get_val() { return *reinterpret_cast<_Tp*>(&_M_val); }
    const _Tp& _M_get_val() const { return *reinterpret_cast<const _Tp*>(&_M_val); }
    _Er& _M_get_err() { return *reinterpret_cast<_Er*>(&_M_err); }
    const _Er& _M_get_err() const { return *reinterpret_cast<const _Er*>(&_M_err); }
};

三、GCC vs LLVM 差异对比

┌────────────────────────┬──────────────────────┬──────────────────────┐
│ 特性                    │ GCC (libstdc++)      │ LLVM (libc++)        │
├────────────────────────┼──────────────────────┼──────────────────────┤
│ expected               │ 支持                 │ 支持                 │
│ unexpected             │ 支持                 │ 支持                 │
│ has_value              │ 支持                 │ 支持                 │
│ value                  │ 支持                 │ 支持                 │
│ error                  │ 支持                 │ 支持                 │
│ transform              │ 支持                 │ 支持                 │
│ and_then               │ 支持                 │ 支持                 │
│ or_else                │ 支持                 │ 支持                 │
└────────────────────────┴──────────────────────┴──────────────────────┘

延伸阅读

基于 MIT 许可发布