std::variant 的多态构造
Polymorphic construction of a std::variant
我想实现一个简单的错误 return 类型,即一种情况表示错误而另一种情况表示成功计算结果的变体。对于该任务,我想像这样创建错误构造函数:
#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*
.
统一起来
有没有办法实现这样的功能?
您可以让您的 make_left_int()
return int
,因为任何 result_t<T>
都可以从 int
构造。但是请注意,您可能会遇到 result_t<int>
的麻烦。
建议自己写一个result
类型,不要依赖variant
。这样做的好处是,您可以处理此类情况(具有 result<int>
),并且它允许您以自己的方式在实际存储错误时处理对值的访问。
The constructor make_left_int
...
但是 make_left_int
不是 C++ 中的构造函数。与您可能使用其术语的函数式语言不同,C++ 构造函数是 class 的一种特殊方法,用于初始化 class 的实例。它不能是一个自由函数,它只是 returns class.
的一个实例
... polymorphic regarding the type of the success variant
是的,但是:C++ 模板类型推导仅对函数的参数 进行操作。例如,
template <typename T> T return_default() { return T{}; }
在此代码中不起作用,因为 return 类型不可用于推导类型参数 T:
int i = return_default();
double d = return_default();
尽管您仍然可以显式传递类型参数:
int i = return_default<int>();
最简单的解决方案是评论中提出的 _nh:从调用中推导出 return 类型,而不是相反(这避免了需要指定结果类型的地方相乘)
auto a = make_left_int<double>();
我怀疑指定成员的含义而不是它在记录中的位置也是更好的样式,例如
auto a = error_result<double>(42);
或者您可以使用实际的构造函数,用于您自己的变体样式 class,最好使用标记类型来区分错误代码和成功代码,以防成功结果也可以是 int:
result<double> a(Error{42});
注意。 C++ 中的 polymorphic 默认情况下通常被假定为 runtime 多态性,与此处讨论的 static/compile-time 多态性相反。如果您使用 template
关键字,您总是可以只说 template 并被理解。
我想实现一个简单的错误 return 类型,即一种情况表示错误而另一种情况表示成功计算结果的变体。对于该任务,我想像这样创建错误构造函数:
#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*
.
有没有办法实现这样的功能?
您可以让您的 make_left_int()
return int
,因为任何 result_t<T>
都可以从 int
构造。但是请注意,您可能会遇到 result_t<int>
的麻烦。
建议自己写一个result
类型,不要依赖variant
。这样做的好处是,您可以处理此类情况(具有 result<int>
),并且它允许您以自己的方式在实际存储错误时处理对值的访问。
The constructor
make_left_int
...
但是 make_left_int
不是 C++ 中的构造函数。与您可能使用其术语的函数式语言不同,C++ 构造函数是 class 的一种特殊方法,用于初始化 class 的实例。它不能是一个自由函数,它只是 returns class.
... polymorphic regarding the type of the success variant
是的,但是:C++ 模板类型推导仅对函数的参数 进行操作。例如,
template <typename T> T return_default() { return T{}; }
在此代码中不起作用,因为 return 类型不可用于推导类型参数 T:
int i = return_default();
double d = return_default();
尽管您仍然可以显式传递类型参数:
int i = return_default<int>();
最简单的解决方案是评论中提出的 _nh:从调用中推导出 return 类型,而不是相反(这避免了需要指定结果类型的地方相乘)
auto a = make_left_int<double>();
我怀疑指定成员的含义而不是它在记录中的位置也是更好的样式,例如
auto a = error_result<double>(42);
或者您可以使用实际的构造函数,用于您自己的变体样式 class,最好使用标记类型来区分错误代码和成功代码,以防成功结果也可以是 int:
result<double> a(Error{42});
注意。 C++ 中的 polymorphic 默认情况下通常被假定为 runtime 多态性,与此处讨论的 static/compile-time 多态性相反。如果您使用 template
关键字,您总是可以只说 template 并被理解。