I am using std::variant and std::visit to call operator functions. I have a lot of variants (which mostly inherit from one superclass), but most of the operator functions should return the same value. Is there a way to have one operator function, which is called everytime one of those child-classes is called (such as if a normal function is called with a child-class as a parameter and if there is no such function, the (overlaoded) function is called, if the super-class is a parameter.
This may be easier to understand with an example:
I have two superclasses:
struct function_node; struct nary_node;
I also have multiple classes which inherit from those superclasses:
struct addition_node : function_node, nary_node;
struct division_node: function_node, nary_node;
struct cos_node: function_node, nary_node;
I have another class which has those classes as variants:
struct value_node{
var get_variant(){
return std::variant<
addition_node*,
division_node*,
cos_node*
>;
}
};
I finally have a last class (constant_checker), which evaluates the expressions.
double eval(value_node* node){
return std::visit(*this, node->get_variant());
}
In this last class I am currently having multiple operator functions of the form:
double operator(division_node* node){
return 0;
}
This works fine, but I actually have multiple dozen of those children-nodes. Since the operator function should all return the same value, I want a single operator function for this, e.g.
double operator(function_node* node){
return 0;
}
I have tried it in this exact way, but I receive the error
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
This error will go away, if I insert the operator function for this exact node (minus_node in this case) and then occurr again for the other nodes, so appearently the general oeprator function is not called.
Is there any solution to this or do I have to keep every operator function?
CodePudding user response:
Just use template 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>) {
// ...
}
}
CodePudding user response:
Your visitor should be in a way that all:
visitor(variant1);
visitor(variant2);
- ..
visitor(variantN);
are valid.
So yes you can group some.
Here
double operator(function_node* node){ return 0; }
would suffice.
Demo.