深入探讨expectedscalartypelongbut的本质

发布时间:2023-05-19

一、expectedscalartypelongbut的定义

template<typename T> 
class expected {
public:
    // construction
    expected() = delete;
    template<typename... Args,
        typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
    explicit expected(in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>);
    template<typename U, typename... Args,
        typename = std::enable_if_t<std::is_constructible_v<T, std::initializer_list<U>&, Args...>>>
    explicit expected(in_place_t, std::initializer_list<U> ilist, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>);
    template<typename U = T,
        typename = std::enable_if_t<std::is_copy_constructible_v<U>>>
    expected(const expected& rhs);
    template<typename U = T,
        typename = std::enable_if_t<std::is_move_constructible_v<U>>>
    expected(expected&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>);
    template<typename U,
        typename = std::enable_if_t<std::is_constructible_v<T, U>>>
    expected(U&& v);
    template<typename U,
        typename = std::enable_if_t<std::is_constructible_v<T, const U&>>>
    expected(const U& v);
    template<typename U, typename... Args,
        typename = std::enable_if_t<std::is_constructible_v<T, std::initializer_list<U>&, Args...>>>
    expected(std::initializer_list<U> il, Args&&... args);
    template<typename U,
        typename = std::enable_if_t<std::is_constructible_v<T, U>>>
    expected& operator=(U&& v);
    template<typename U,
        typename = std::enable_if_t<std::is_constructible_v<T, const U&>>>
    expected& operator=(const U& v);
    // access
    constexpr const T* operator->() const;
    constexpr T* operator->();
    constexpr const T& operator*() const&;
    constexpr T& operator*() &;
    constexpr explicit operator bool() const noexcept;
    constexpr bool has_value() const noexcept;
    // error handling
    constexpr const E& error() const&;
    constexpr E& error() &;
    // swap
    void swap(expected& rhs) noexcept(std::is_nothrow_move_constructible_v<T>&& std::is_nothrow_swappable_v<T>&& std::is_nothrow_swappable_v<E>);
    // unexpected value handling
    template<typename F>
    expected<T, E>& map_error(F f);
};

expectedscalartypelongbut 是C++ STL库中的一种类型,它被用于函数返回值,它的主要实现思路是:当函数的返回值存在错误时,返回一个 expected 对象,以此来告诉调用方已经发生了错误,可以通过该对象的 error() 方法获取到错误信息。

二、expectedscalartypelongbut的构造函数

expectedscalartypelongbut 提供了多个构造函数,下面简要介绍这几种常用的构造函数:

1. expected()

这个构造函数是 expectedscalartypelongbut 类的默认构造函数,但是这个函数是 delete 掉,意思是我们不能直接调用这个构造函数来创建一个 expectedscalartypelongbut 对象。

2. expected(in_place_t, Args&&... args)expected(in_place_t, std::initializer_list<U> ilist, Args&&... args)

template < typename... Args, 
           typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
explicit expected(in_place_t, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>); 
template<typename U, typename... Args,
         typename = std::enable_if_t<std::is_constructible_v<T, std::initializer_list<U>&, Args...>>>
explicit expected(in_place_t, std::initializer_list<U> ilist, Args&&... args) noexcept(std::is_nothrow_constructible_v<T, std::initializer_list<U>&, Args...>);

我们分别看这两个构造函数的声明,这两个构造函数的主要作用是用来通过参数直接构造 expectedscalartypelongbut 对象,而并非拷贝构造或者移动构造。其中,in_place_t 是一个空结构体,它的作用是表示使用in-place构造。对于第一个构造函数,我们需要传入一系列的参数 Args,可以在 expectedscalartypelongbut 对象中对传入的参数进行构造。而第二个构造函数需要先传入一个 std::initializer_list 作为初始参数,之后我们可以访问这个条件列表中的元素,同时再提供一些其他的参数 Args

3. expected(const expected& rhs)expected(expected&& rhs)

template<typename U = T,
        typename = std::enable_if_t<std::is_copy_constructible_v<U>>>
expected(const expected& rhs);
template<typename U = T,
        typename = std::enable_if_t<std::is_move_constructible_v<U>>>
expected(expected&& rhs) noexcept(std::is_nothrow_move_constructible_v<T>);

这两个构造函数的作用是使用已有的 expectedscalartypelongbut 对象创建一个新的 expectedscalartypelongbut 对象。当我们调用拷贝构造函数时,内部会对 rhs 对象进行复制,而调用移动构造函数时,则是将 rhs 的值全部转移到新生成的 expectedscalartypelongbut 对象中。

三、expectedscalartypelongbut 的访问函数以及异常处理

expectedscalartypelongbut 的核心作用是用来表示函数返回值中的错误信息,在我们使用时,除了前文提到的构造函数以外,还有一些访问函数以及一些异常处理方式:

1. operator->()operator*

这些函数的作用主要是方便我们访问 expectedscalartypelongbut 对象内嵌的数据。比如,在我们需要使用 expectedscalartypelongbut 对象返回一个指针时,就可以通过 operator-> 函数来访问指针。而 operator*() 函数则是方便我们访问 std::optional 中的数据。

2. operator bool()has_value()

constexpr explicit operator bool() const noexcept;
constexpr bool has_value() const noexcept;

expectedscalartypelongbut 对象包含合法的数值时,而没有错误的话,这两个函数会返回 true。反之,如果 expectedscalartypelongbut 对象包含了一个 error() 信息,这两个函数都会返回 false

3. error()map_error()

constexpr const E& error() const&;
constexpr E& error() &;
template<typename F>
expected<T, E>& map_error(F f);

当我们调用 error() 函数时,它会返回一个生成 expectedscalartypelongbut 对象的异常信息。如果 expectedscalartypelongbut 对象无错误,该函数将抛出异常,我们可以通过 map_error() 函数来处理。 map_error() 函数的作用是映射参数函数 f,如果 expectedscalartypelongbut 对象有异常信息,它会用 f 将异常信息映射为新的异常信息。这一过程也被称作 functor 调用,它使用一个函数将异常信息传入,同时返回新的异常信息。这一过程不改变当前对象的状态,而只是返回映射后的新 expectedscalartypelongbut 对象。

四、expectedscalartypelongbut 的使用场景

expectedscalartypelongbut 在应用中被广泛使用,特别是在函数的返回值中。当我们使用 expectedscalartypelongbut 时,我们应该优先考虑函数返回值中是否会存在错误。如果函数存在潜在的错误情况,我们就可以选择使用 expectedscalartypelongbut 对象作为该函数的返回值。由于 expectedscalartypelongbut 对象可以在出现错误时,直接返回一个 error 信息,它因此可以帮助开发者更好地进行错误处理和处理异常情况。

五、总结

本文针对 expectedscalartypelongbut 这一模板的使用进行了详细地介绍。我们分步介绍了 expectedscalartypelongbut 的定义、构造函数、访问函数以及异常处理机制,并提到了其广泛的应用场景。在使用 expectedscalartypelongbut 进行函数返回值时,可以通过它快速发现异常情况,并及时进行错误处理,因此它大大方便了函数调用和开发者的开发体验。