重构以返回多个“信息”

时间:2016-02-11 09:56:41

标签: c++ c++11 boost c++14

我有一个由外部库提供的类型T,我的虚拟成员函数f声明如下,在我的程序中被许多类型覆盖:

virtual T MyType1::f(input_t in);
virtual T MyType2::f(input_t in);
virtual T MyType3::f(input_t in);

现在我需要一种方法来根据T的特定值向呼叫者返回替代的“互斥”信息 - 这与in无关。遗憾的是,我无法在T域中返回任何特殊值,因此我担心我必须重构f()的声明。

我看到了这些可能性:

  1. 重构TW MyType::f(input_t),其中W是包装器 大约T,加上另一个成员数据和T的强制转换操作符 我可以像以前一样使用W作为T,除了少数几个 我需要检查u值的地方,例如struct W {T t; U u; operator T();};
  2. 重构Tvariant <T, U>
  3. 重构fT MyType::f(input_t in, U& out);
  4. 重构fstd::tuple<T, U> MyType::f(input_t);
  5. 我认为使用变体是最好的选择。你觉得怎么样?

1 个答案:

答案 0 :(得分:2)

结合1和2:

您获得了自己类型之一的抽象,您可以更好地记录和测试结果类型的不变量,并且可以使用variant<T,U>实现结果类型抽象。

比较这两段代码的客户端代码:

struct W
{
    operator T& (); // throws T_not_generated
    bool succeeeded() const;
private:
    variant <T, U> data;
};

virtual W MyType1::f(input_t in);

客户代码:

MyType1 a;
T t1 = a.f(in);
auto r2 = a.f(in);
if(r2.succeeded())
{
    T t2 = r2;
}

有了这个:

virtual variant <T, U> MyType1::f(input_t in);

客户代码:

MyType1 a;
try
{
    auto T1 boost::get<T>(a.f(in));
    auto r2 = a.f(in);
    if(??)
    {
        T t2 = boost::get<T>(r2);
    }
}
catch(const boost::<what's the error type?>& error)
{
    ///... 
}

我的观点是( tldr ):你应该考虑抽象出结果的处理(并在其上施加你需要的任何不变量),但你仍然可以在场景后面使用boost :: variant