我有一个由外部库提供的类型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()
的声明。
我看到了这些可能性:
T
为W MyType::f(input_t)
,其中W
是包装器
大约T
,加上另一个成员数据和T
的强制转换操作符
我可以像以前一样使用W
作为T
,除了少数几个
我需要检查u
值的地方,例如struct W {T t;
U u; operator T();};
T
为variant <T, U>
f
为T MyType::f(input_t in, U& out);
f
为std::tuple<T, U> MyType::f(input_t);
我认为使用变体是最好的选择。你觉得怎么样?
答案 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