【问题标题】:How is it possible to unite multiple types in the operator function called by std::visit in C++?如何在 C++ 中 std::visit 调用的运算符函数中联合多种类型?
【发布时间】:2021-10-28 08:01:44
【问题描述】:

我正在使用 std::variant 和 std::visit 来调用运算符函数。我有很多变体(主要从一个超类继承),但大多数运算符函数应该返回相同的值。有没有办法拥有一个运算符函数,每次调用其中一个子类时都会调用该函数(例如,如果使用子类作为参数调用普通函数并且如果没有这样的函数,则(重载) 函数被调用,如果超类是一个参数。

举个例子可能更容易理解:

我有两个超类: struct function_node; struct nary_node; 我还有多个继承自这些超类的类:

struct addition_node : function_node, nary_node;
struct division_node: function_node, nary_node;
struct cos_node: function_node, nary_node;

我有另一个类具有这些类作为变体:

struct value_node{
   var get_variant(){
      return std::variant<
                 addition_node*,
                 division_node*,
                 cos_node*
              >;
   }
};

我终于有了最后一个类 (constant_checker),它计算表达式。

double eval(value_node* node){
   return std::visit(*this, node->get_variant());
}

在这最后一堂课中,我目前有多个运算符函数的形式:

double operator(division_node* node){
   return 0; 
}

这很好用,但我实际上有几十个这样的子节点。由于操作符函数都应该返回相同的值,所以我想要一个操作符函数,例如

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

如果我为这个确切的节点(在这种情况下为减节点)插入运算符函数,然后为其他节点再次发生,这个错误就会消失,所以显然没有调用一般的运算符函数。

是否有任何解决方案或者我必须保留每个操作员功能?

【问题讨论】:

    标签: c++ operator-overloading std-variant


    【解决方案1】:

    只需使用模板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>) {
        // ...
      }
    }
    

    【讨论】:

      【解决方案2】:

      您的访问者应该是:

      • visitor(variant1);
      • visitor(variant2);
      • ..
      • visitor(variantN);

      有效。

      所以是的,你可以分组一些。

      这里

      double operator(function_node* node){ return 0; }
      

      足够了。

      Demo.

      【讨论】:

      • 但不幸的是,我仍然收到错误消息,即使我认为所有访问者都应该是有效的。我给出的例子可能有点狭窄,实际上有数百个嵌套类。例如减节点结构 minus_node : derived_value_node>, unary_node> {using kary_node::kary_node;};即使存在derived_value_node 和kary_node 的运算符(我也尝试过unary_node),却给了我一个错误。
      • @wittn:下一次,创建MCVE。正如问题已得到解答。你可能应该问另一个问题。 (以破坏现有答案的方式修改问题是不好的)。
      猜你喜欢
      • 1970-01-01
      • 2020-05-12
      • 2015-11-02
      • 1970-01-01
      • 1970-01-01
      • 2019-02-08
      • 1970-01-01
      • 1970-01-01
      • 2019-02-18
      相关资源
      最近更新 更多