std ::变体的多态构造

时间:2017-09-08 12:39:28

标签: c++ polymorphism variant

我想实现一个简单的错误返回类型,即一个案例表示错误而另一个表示成功计算结果的变体。对于那个任务,我想创建像这样的错误构造函数:

#include <variant>
#include <string>
#include <iostream>

template <typename A> using result_t = std::variant<int, A> ;

template <typename T> result_t<T> make_left_int()
{
    return 42;
}

int main ()
{
    result_t<double> a = make_left_int();
    result_t<void*> b = make_left_int();

    std::cout << std::get<int>(a) << std::endl << std::get<int>(b) << std::endl;
}

构造函数make_left_int在成功变体的类型方面具有多态性。但显然,C ++编译器无法输入它。它无法推断(未使用的)模板参数T.或者它无法将其与doublevoid*统一起来。

有没有办法拥有这样的功能?

2 个答案:

答案 0 :(得分:2)

  

构造函数make_left_int ...

但是make_left_int不是C ++中的构造函数。与您可能使用的术语的函数式语言不同,C ++构造函数是类的特殊方法,用于初始化该类的实例。它不能是一个只是返回该类实例的自由函数。

  

...关于成功变体类型的多态性

是,但是:C ++模板类型推导仅对函数的参数进行操作。例如,

template <typename T> T return_default() { return T{}; }

无法使用此代码,因为返回类型不可用于推断类型参数T:

int i = return_default();
double d = return_default();

虽然你仍然可以明确地传递type参数:

int i = return_default<int>();

最简单的解决方案是在注释中提出的一个_nh:从调用中推导出返回类型,而不是相反(这避免了将指定结果类型所需的位置相乘)

auto a = make_left_int<double>();

我怀疑指定成员的意思是更好的风格,而不是它在记录中的位置,例如

auto a = error_result<double>(42);

或者您可以使用实际的构造函数,对于您自己的变体样式类,理想情况下使用标记类型来区分错误代码和成功,以防成功结果也可以是int:

result<double> a(Error{42});

NB。默认情况下,C ++中的 polymorphic 通常被认为是指 runtime 多态,而不是这里讨论的静态/编译时多态。如果您使用template关键字,则可以随时说模板并理解。

答案 1 :(得分:0)

您可以让make_left_int()返回int,因为任何result_t<T>都可以从int构建。但请注意,您可能会遇到result_t<int>的问题。

我建议您自己编写result类型,而不是依赖variant。这样做的好处是,您可以处理此类情况(具有result<int>),并且它允许您以自己的方式处理实际存储错误时对值的访问。