C++ 编写一个通用的遍历函数,允许灵活地处理具有不同参数的多个函数

C++ 编写一个通用的遍历函数,允许灵活地处理具有不同参数的多个函数,c++,function,data-structures,binary-search-tree,C++,Function,Data Structures,Binary Search Tree,我想使用std::function来帮助我运行一个遍历BST并调用参数化函数的通用遍历函数 我的困难是,参数化函数在其自身参数中是不同的 //populates an array with the values in the BST by traversing the BST void LinkedBST<T>::populate(T const * const data, size_t & I, Node *x) { data[i++] = x->val

我想使用std::function来帮助我运行一个遍历BST并调用参数化函数的通用遍历函数

我的困难是,参数化函数在其自身参数中是不同的

//populates an array with the values in the BST by traversing the BST
void LinkedBST<T>::populate(T const * const data, size_t & I, Node *x)

{
      data[i++] = x->val;
}

//insert unique values of another BST into "this" BST: traverses the other BST and inserts every value
void LinkedBST<T>::insert(Node *x)
{
      insert(x->val);
}
例如,我要概括以下三个函数(它们的参数都不同)

//通过遍历BST,用BST中的值填充数组
void LinkedBST::填充(T常量*常量数据、大小\u T&I、节点*x)
{
数据[i++]=x->val;
}
//将另一个BST的唯一值插入“this”BST:遍历另一个BST并插入每个值
void LinkedBST::insert(节点*x)
{
插入(x->val);
}
与为上述每个函数编写单独的遍历函数不同,我希望能够将它们传递到一个通用遍历函数中,类似于:

void LinkedBST<T>::traverse(Node *x, auto func)
{
     if(x == nullptr)
          return;

     traverse(x->left, func);
     func( <parameters> );
     traverse(x->right, func);
}
void linkedbtst::遍历(节点*x,自动函数)
{
如果(x==nullptr)
返回;
横移(x->左,func);
func();
遍历(x->右,func);
}
有没有办法做到这一点?如果有,你能帮我做吗


谢谢:)

通常,您需要找到一种方法来标准化所有遍历回调的签名。一种选择是使用lambdas并利用lambda捕获来减少函数的参数数量

void LinkedBST<T>::populate(T const * const data, size_t & I)
{
    traverse(root, [&](Node * x) {
            data[i++] = x->val;
        });
}
void LinkedBST::填充(T常量*常量数据,大小\u T&I)
{
遍历(根,[&](节点*x){
数据[i++]=x->val;
});
}

请注意,相同的遍历函数不能用于
compare
,因为您需要同时遍历两棵树。现在还不清楚insert应该做什么,但从注释来看,它似乎也需要同时遍历。

一个解决方案是将遍历函数模板化以获取函数对象。然后,将这些参数移动到函数对象,让函数对象的
操作符()处理调用时的细节,而不是在
遍历
函数中指定参数:

template <typename func>
void LinkedBST<T>::traverse(Node *x, func fn)
{
     if(x == nullptr)
          return;

     traverse(x->left, fn);
     fn(x->val);
     traverse(x->right, fn);
}

struct some_func
{
   int param1;
   int param2;
   int param3;

   some_func(int p1, int p2, int p3) : param1(p1), param2(p2), param3(p3) {}
   void operator()(int node_value) 
   {
      std::cout << "The node value is " << node_value << "\n";
      // the parameters are param1, param2, param3
   }
};
下面是一个示例,通过使用一个虚拟类来展示基本知识


您也可以将lambda与此技术结合使用:

Node *node_ptr;
//...
LinkedBST<int> the_list;
//...
int arg1=1, arg2=2, arg3=3;
the_list.traverse(node_ptr, 
                  [&](int node_value){std::cout << "The node value is " << 
                                      node_value << "\n" << arg1 << " " << 
                                      arg2 << " " << arg3;});
Node*Node\u ptr;
//...
LinkedBST_列表;
//...
int arg1=1,arg2=2,arg3=3;
_list.transverse(节点_ptr,

[&](int node_value){std::cot Try a,你会很快得到指示。嘿,特德!不确定你的意思。什么是[mvce]?嘿,特德。谢谢你的反馈!:)新到该网站。所以,我不确定这意味着什么。我的答案是不完整的还是不是最小的——也就是说,我应该添加更多细节,还是删除一些?@RafaelVergnaud了解。@RafaelVergnaud您所说的问题有所改进-但是,这不是一个最小和完整的例子,我可以用来验证您的说法。嘿,Peter。谢谢您的回复嘿,保罗!谢谢你的回答!
Node *node_ptr;
//...
LinkedBST<int> the_list;
//...
int arg1=1, arg2=2, arg3=3;
the_list.traverse(node_ptr, 
                  [&](int node_value){std::cout << "The node value is " << 
                                      node_value << "\n" << arg1 << " " << 
                                      arg2 << " " << arg3;});