我想实现一个简单的错误返回类型,即一个案例表示错误而另一个表示成功计算结果的变体。对于那个任务,我想创建像这样的错误构造函数:
#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.或者它无法将其与double
和void*
统一起来。
有没有办法拥有这样的功能?
答案 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>
),并且它允许您以自己的方式处理实际存储错误时对值的访问。