4

我想实现一个类 FuncWrapper,它的行为如下所示,但我发现它并不像预期的那么容易。

int OrdinaryFunction(int n)
{
    return n;
}

struct Functor
{
    int operator ()(int n)
    {
        return n;
    }
};

int main()
{
    FuncWrapper<int(int)> f1(OrdinaryFunction);
    cout << f1(1); // output 1;

    Functor functor;
    FuncWrapper<int(int)> f2(functor);
    cout << f2(2); // output 2;

    return 0;
}

我的问题是:如何在 PURE C++(即没有 STL)中实现类 FuncWrapper 来编译代码?

我部分实施了 FuncWrapper,如下所示:

template<class T>
class FuncWrapper;

template<class ReturnType, class Parameter1>
class FuncWrapper<ReturnType(Parameter1)>
{
public:
    typedef ReturnType (*FunctionPtr)(Parameter1);

    template<class Functor>
    FuncWrapper(Functor fn) 
    {
        // ???
    }

    FuncWrapper(FunctionPtr fn)
        : fn(fn)
    {}

    ReturnType operator ()(Parameter1 p1)
    {
          return this->fn(p1);          
    }

private:
    FunctionPtr fn;
};
4

2 回答 2

3

好吧,你可能认为做你正在尝试的事情很简单,但它非常复杂。

在您的情况下,您希望能够添加一个仿函数以及一个实际函数,这使事情变得复杂。毕竟,如果您的类将构造函数用于称为 Functor 的仿函数,那么您将在哪里存储对象?

boost 在其共享指针类中用于存储删除器的一种方法是实际拥有一个基类和一个派生类。您的构造函数将构造一个派生自基类的对象(带有 new),然后您使用多态性来调用。

boost 在其函数和 binder / mpl 库中使用了各种巧妙的技术,但现在我建议你使用这个。

如果你真的反对使用 boost 或任何类型的共享指针,你将不得不管理这个对象的内存。(烦人,因为你希望你的外部类是可复制和可分配的)。

我将使它变得简单,并说我可以使用 shared_ptr。我现在也将简化签名。

作为大纲...

template< typename R, typename P > class FunctorBase
{
 public:
      virtual ~FunctorBase() {}
      virtual R call(P p) = 0;
};

template< typename R, typename P > class FunctionWrapper
{
     shared_ptr< FunctorBase< R, P > > impl;
  public:
     template< typename F > // a functor
     FunctionWrapper( Functor f )
     {
          // create appropriate impl for functors
     }

     FunctionWrapper( (R (func*)(P) )
     {
          // create appropriate impl for functions
     }

     R operator()( P p )
     {
          return impl->call(p);
     }
};

您的仿函数实现可能类似于:

template< typename R, typename P, typename F >
class FunctorImpl : public FunctorBase< R, P >
{
    F f;

   public: 
     FunctorImpl( F fparam ) : f( fparam )
     {
     }

     R call( P p )
     {
        return f( p );
     }
};

所以现在你看到了你可以在哪里存储仿函数..

于 2012-11-05T17:08:36.260 回答
0

只需向您的仿函数添加一个构造函数,该构造函数接受指向函数的指针(带有您想要的函数签名)。将指针存储在函子中并从 operator() 执行指向的函数。

如果我对您的理解正确,您需要一个包装器,该包装器将为仿函数和函数公开类似函数的行为。在包装器中存储指向函子的指针,而不是指向函数的指针。以函子为参数的构造函数将把函子存储在里面。以 func 作为参数的构造函数将创建一个仿函数(就像我在答案中写的那样)并将其存储在里面。

于 2012-11-05T16:31:47.063 回答