c++ - (boost::)outcome 的错误处理:在具有组合和继承的构造函数中使用

标签 c++ boost error-handling c++17

在我的环境中,我不能使用异常,所以我需要一个替代解决方案来处理错误。在新的现代项目中,将 int 作为错误代码返回不是一个好方法,因为此接口(interface)会阻止返回其他数据。
std::expected 尚不可用;也许有一些示例实现,但我需要一些已经测试过且健壮的东西。
我正在评估 (boost::) 结果 https://ned14.github.io/outcome/它似乎符合我的需求:它有一个清晰的界面,如果不使用辅助有效负载,它应该非常高效。
泛型类方法的用例非常简单:https://ned14.github.io/outcome/tutorial/essential/result/
关于构造函数的使用,作者建议使用双阶段构造(https://ned14.github.io/outcome/tutorial/advanced/constructors/)。
本教程不讨论类组合和继承。以下示例与教程相同。

class A {
protected: // use protected because of C class in the next example
    constexpr A() noexcept { /*...*/ }
public:
    ~A() noexcept { /*...*/ }

    A( A&& rhs ) noexcept { /*...*/ }

    A& operator=( A&& rhs ) noexcept 
    {
        this->~A();
        new(this) A( std::move( rhs ) );
        return *this;
    }

    // Remove copy ctor and assignment op
    A( const A& ) = delete;
    A& operator=( const A& ) = delete;

    /** Static member constructor */
    static result<A> A_ctor() noexcept 
    {
        // Phase 1 ctor
        A ret;
        // Phase 2 ctor
        if ( /*something goes wrong*/ ) return MyErrorCode::Error;
        return { std::move( ret ) };
    }

    void a_method() noexcept { /*...*/ }
};

template<> struct make<A>
{
    result<A> operator()() const noexcept
    {
        return A::A_ctor();
    }
};
现在考虑包含类 A 的类 B。作为 protected A ctor,以下声明无效:
class B {
    A a_;
    ...
};
也许以下方法可以工作:
class B {
    result<A> a_;
    constexpr B() noexcept : a_( make<A>{}() ) {}
public:
    static result<B> B_ctor() noexcept
    {
        // Phase 1 ctor
        B ret;
        // Phase 2 ctor
        if ( ret.value().a_.has_failure() ) return MyErrorCode::Error;
        if ( /*something else goes wrong*/ ) return MyErrorCode::AnotherError;
        return { std::move( ret ) };
    }

    // ...

    void b_method() noexcept
    {
        a_.value().a_method(); // <-- ugly!
        // ...
    }
};
但使用 result<A>作为 a_ 的类型不是很好。它需要使用a_.value()代码中的任何地方a_用来。此外,如果 a_经常使用,可能会降低效率。还有其他解决方案吗?
派生类还有另一个暗点。
class C : public A {
    constexpr C() noexcept : A() { /*...*/ }
public:
    // ...

    static result<C> C_ctor() noexcept
    {
        // Phase 1 ctor
        C ret;
        // Phase 2 ctor
        // How to reuse A ctor???
        // ...
        return { std::move( ret ) };
    }
};
C_ctor我想从 A_ctor 开始构建类(class)为避免代码重复,例如:
result<C> ret = C::A_ctor();
但没有可用的转换。有什么想法可以解决这个问题吗?

最佳答案

Being A ctor protected, the following declaration is not valid.


您确实不能使用不可访问的构造函数,但移动构造函数是公共(public)的,
所以你可以写你的X_ctor不同:
B(A&& a) noexcept : a_(std::move(a)) {} // use public A(A&&)

static result<B> B_ctor() noexcept
{
    result<A> a = make<A>(); 
    if ( a.has_failure() ) return MyErrorCode::Error;

    // Phase 1 ctor
    B ret(std::move(a.value()));

    // Phase 2 ctor
    if ( /*something else goes wrong*/ ) return MyErrorCode::AnotherError;
    return { std::move( ret ) };
}

In C_ctor I would like to construct the class starting from A_ctor to avoid code duplication


你可能有 init职能:
result<bool> init() noexcept 
{
    // ...
    if ( /*something goes wrong*/ ) return MyErrorCode::Error;
    return {true};
}

static result<A> A_ctor() noexcept 
{
    // Phase 1 ctor
    A ret;
    // Phase 2 ctor
    result<bool> a_init = ret.init();
    if ( a_init.has_failure() ) return a_init.error();
    return { std::move( ret ) };
}
result<bool> init() noexcept 
{
    result<bool> a_init = A::init();
    if ( a_init.has_failure() ) return a_init.error();

    // ...
    if ( /*something goes wrong*/ ) return MyErrorCode::Error;
    return {true};
}

static result<C> C_ctor() noexcept
{
    // Phase 1 ctor
    C ret;

    // Phase 2 ctor
    result<bool> c_init = ret.init();
    if ( c_init.has_failure() ) return c_init.error();
    return { std::move( ret ) };
}

关于c++ - (boost::)outcome 的错误处理:在具有组合和继承的构造函数中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65415896/

相关文章:

php - 如何在 PHP 7+ 中捕获可恢复的错误?

c++ - PDF渲染库

C++ ffmpeg 访问冲突

c++ - 使用 boost 几何缓冲区缩放多边形时的冗余顶点

c++ - 是否可以从 C printf() 捕获错误?

java - 在类中实现类

c++ - 这会彻底清除类对象动态分配的结果吗?

c++ - 基于 x 和 y 坐标排序

c++ - 在 CodeBlocks 中链接 Boost 库(使用 MinGW)

c++ - 如何使用 boost 将流放入缓冲区