在 C++ 中 std::visit 调用的运算符函数中如何合并多个类型?
How is it possible to unite multiple types in the operator function called by std::visit in C++?
我正在使用 std::variant 和 std::visit 调用运算符函数。我有很多变体(大部分继承自一个 superclass),但大多数运算符函数应该 return 相同的值。有没有一种方法可以拥有一个运算符函数,每次调用这些 child-classes 中的一个时都会调用该函数(例如,如果使用 child-class 作为参数调用普通函数,并且如果没有这样的函数,如果 super-class 是参数,则调用(overlaoded)函数。
举个例子可能更容易理解:
我有两个超级classes:
struct function_node; struct nary_node;
我还有多个 classes 继承自那些 superclasses:
struct addition_node : function_node, nary_node;
struct division_node: function_node, nary_node;
struct cos_node: function_node, nary_node;
我有另一个 class 有那些 classes 作为变体:
struct value_node{
var get_variant(){
return std::variant<
addition_node*,
division_node*,
cos_node*
>;
}
};
我终于有了最后一个 class (constant_checker),它计算表达式。
double eval(value_node* node){
return std::visit(*this, node->get_variant());
}
在最后一个 class 中,我目前有多个运算符函数的形式:
double operator(division_node* node){
return 0;
}
这很好用,但实际上我有很多这样的子节点。由于运算符函数应该都是 return 相同的值,因此我需要一个运算符函数,例如
double operator(function_node* node){
return 0;
}
我已经按照这个方法试过了,但是我收到了错误
3>C:\...\include\variant(1644): error C2893: Failed to specialize function template 'unknown-type std::_C_invoke(_Callable &&,_Types &&...) noexcept(<expr>)'
3>C:\...\include\variant(1644): note: With the following template arguments:
3>C:\...\include\variant(1644): note: '_Callable=ale::util::constant_checker &'
3>C:\...\include\variant(1644): note: '_Types={ale::minus_node *}'
3>C:\...\include\variant(1656): error C2955: 'std::_All_same': use of class template requires template argument list
如果我为这个确切的节点(在本例中为 minus_node)插入运算符函数,然后对其他节点再次发生,则此错误将消失,因此显然不会调用通用运算符函数。
是否有任何解决方案,或者我是否必须保留每个运算符功能?
您的访客应该是这样的:
visitor(variant1);
visitor(variant2);
- ..
visitor(variantN);
有效。
所以是的,你可以将一些分组。
这里
double operator(function_node* node){ return 0; }
就够了。
Demo.
只需使用模板 operator()
:
template<class Node>
double operator()(Node* node) {
if constexpr (std::is_same_v<Node, addition_node>) {
// ...
} else if constexpr (std::is_same_v<Node, division_node>) {
// ...
}
}
我正在使用 std::variant 和 std::visit 调用运算符函数。我有很多变体(大部分继承自一个 superclass),但大多数运算符函数应该 return 相同的值。有没有一种方法可以拥有一个运算符函数,每次调用这些 child-classes 中的一个时都会调用该函数(例如,如果使用 child-class 作为参数调用普通函数,并且如果没有这样的函数,如果 super-class 是参数,则调用(overlaoded)函数。
举个例子可能更容易理解:
我有两个超级classes:
struct function_node; struct nary_node;
我还有多个 classes 继承自那些 superclasses:
struct addition_node : function_node, nary_node;
struct division_node: function_node, nary_node;
struct cos_node: function_node, nary_node;
我有另一个 class 有那些 classes 作为变体:
struct value_node{
var get_variant(){
return std::variant<
addition_node*,
division_node*,
cos_node*
>;
}
};
我终于有了最后一个 class (constant_checker),它计算表达式。
double eval(value_node* node){
return std::visit(*this, node->get_variant());
}
在最后一个 class 中,我目前有多个运算符函数的形式:
double operator(division_node* node){
return 0;
}
这很好用,但实际上我有很多这样的子节点。由于运算符函数应该都是 return 相同的值,因此我需要一个运算符函数,例如
double operator(function_node* node){
return 0;
}
我已经按照这个方法试过了,但是我收到了错误
3>C:\...\include\variant(1644): error C2893: Failed to specialize function template 'unknown-type std::_C_invoke(_Callable &&,_Types &&...) noexcept(<expr>)'
3>C:\...\include\variant(1644): note: With the following template arguments:
3>C:\...\include\variant(1644): note: '_Callable=ale::util::constant_checker &'
3>C:\...\include\variant(1644): note: '_Types={ale::minus_node *}'
3>C:\...\include\variant(1656): error C2955: 'std::_All_same': use of class template requires template argument list
如果我为这个确切的节点(在本例中为 minus_node)插入运算符函数,然后对其他节点再次发生,则此错误将消失,因此显然不会调用通用运算符函数。
是否有任何解决方案,或者我是否必须保留每个运算符功能?
您的访客应该是这样的:
visitor(variant1);
visitor(variant2);
- ..
visitor(variantN);
有效。
所以是的,你可以将一些分组。
这里
double operator(function_node* node){ return 0; }
就够了。
Demo.
只需使用模板 operator()
:
template<class Node>
double operator()(Node* node) {
if constexpr (std::is_same_v<Node, addition_node>) {
// ...
} else if constexpr (std::is_same_v<Node, division_node>) {
// ...
}
}