如果函数对象有许多参数,它们会是什么样子?

时间:2010-09-17 11:33:09

标签: c++

我创建了一个非常简单的Tree实现,我希望能够将一个函数对象传递给我的traverse()函数。 e.g。

template<class T>
class MyTree
{
public:

    void traverse(MyFunction f) {
        traverse(root, f);
    }
private:
      MyTreeNode<T>* root;
      void traverse(MyTreeNode<T>*, MyFunction f);
};

问题是,如果我想传递一些参数以及相关节点,我如何声明f? (指向其他structs的指针)。或者,任何人都可以指向我一些教程的方向吗?

4 个答案:

答案 0 :(得分:2)

一种可能性是使用boost::function并定义一个仅将您的节点作为参数的函数类型。然后,只要绑定其他参数,就可以从任何函数创建boost::function对象。

template<class T>
class MyTree
{
public:
    typedef boost::function< void (MyTreeNode<T>*) > MyFunction;

    void traverse(MyFunction f) {
        traverse(root, f);
    }
private:
      MyTreeNode<T>* root;
      void traverse(MyTreeNode<T>*, MyFunction f);
};

tree.traverse( boost::bind( &func_with_args, _1, arg1, arg2 ) );

答案 1 :(得分:2)

您可以将其设为模板成员函数,

template<class T>
class MyTree
{
public:

    template<typename Functor>
    void traverse(Functor f) {
        traverse(root, f);
    }
private:
      MyTreeNode<T>* root;

      template<typename Functor>
      void traverse(MyTreeNode<T>* node, Functor f) {
         f(node->value);
         // etc...
      }
};

在此表单中,将接受任何可以作为f(x)调用的函数对象。

答案 2 :(得分:1)

在这个阶段你可以做很多事情。

旧式C类型解决方案:您可以传递一个函数指针:

template <typename T>
void MyTree<T>::traverse( void (*function)( MyTreeNode<T>*, int ) );

这将把一个函数指针(自由函数)作为参数,该指针将指向MyTreeNode<T>对象的指针作为第一个参数,将整数作为第二个参数。您可以typedef使用函数类型来简化使用:

template <typename T>
class MyTree {
public:
   typedef void func( MyTreenode<T>*, int );     // typedef the function type
   typedef void (*pfunc)( MyTreenode<T>*, int ); // or the function pointer
   void traverse( func* function );
   void traverse2( pfunc function );
};

您可以借助模板将任何可调用的 thing 作为参数:

template <typename T>
class MyTree {
public:
   template <typename Functor> 
   void traverse( Functor f );
};

如果你让参数类型保持空闲,那么最简单的方法是 simple ,但是如果你尝试传递一个带有不同参数集的可调用实体的错误消息可能不那么简单解析。在内部,您可以使用f,就像它是一个函数一样,但外部可以是函数或函数对象,包括std::bind(c ++ 0x)或boost::bind的结果

您可以向前迈出一步,并使用traverse(再次,c ++ 0x)或{{1}在std::function函数的签名中实际执行您要使用的参数}:

boost::function

这个解决方案的优点是很清楚你将如何使用传入的参数(如在函数指针方法中):你将调用template <typename T> class MyTree { public: void traverse( std::function< void (MyTreeNode<T>*, int )> f ); }; f( x, y )x 1}}和MyTreeNode<T>*是一个整数。同时,您通过y(c ++ 0x)或std::bind提供模板化解决方案的通用性,可用于使不同实体适应boost::bind参数,包括自由函数,函数对象,成员函数......

答案 3 :(得分:1)

如果我理解正确,你就会问起如何宣布仿函数。这是一个小代码,可以给你一个想法。

struct A{
 void operator()(int x, double d){}   // overloaded operator()
};

int main(){
 A a;
 a(2, 3.0);
}