避免显式仿函数模板类型

时间:2013-09-18 10:52:41

标签: c++ templates functor

我在玩弄玩家。我正在使用下面的标准示例:

class C {
public:
    template <typename Func>
    void foo(Func fun)
    {
        fun();
    }
};

struct S {
    void operator()() { printf ("in S\n"); }
};
....
C myClass;
myClass.foo (S());

这很好用,我不需要在调用foo()时显式提供S模板类型,它只是想出来。但是假设我想将仿函数存储为成员变量并稍后调用它:

class C {
public:
    template <typename Func>
    void foo(Func fun) {
        _myFunc = fun;
    }

    void someOtherThing() { 
        _myFunc();
    }
private:
    WHAT_IS_THIS_TYPE _myFunc;
};

我现在需要让整个班级成为模板吗?如果是这样,编译器可以像使用单个仿函数一样推断模板类型,还是必须明确提供它?感谢。

2 个答案:

答案 0 :(得分:4)

您可以使用std :: function(在C ++ 11中)或boost :: function来存储可调用对象(函数,仿函数)。它实现了类型擦除模式。

class C {
public:
  template <typename Func>
  void foo(Func fun) {
    _myFunc = fun;
  }

  void someOtherThing() { 
    _myFunc();
  }
private:

  std::function<void()> _myFunc;
};

答案 1 :(得分:-1)

这是一种避免使类C成为模板的手工制作方式:

struct C {
    template <typename Func>
    void foo(Func fun) {
        _myFunc = static_cast <void*>(&fun);
        stub = call <Func>;
    }

    void someOtherThing() {
        stub(_myFunc);
    }

private:
    void* _myFunc;
    void (*stub)(void*);

    template <typename F>
    static void call(void* f) {
        (*static_cast <F*>(f))();
    }
};

struct S {
    void operator()() { std::cout << "in S" << std::endl; }
};

int main()
{
    S s;
    C myClass;
    myClass.foo(s);
    myClass.someOtherThing();
}

当您致电foo()时,在模板静态函数Func中“存储”call,这是指向stub存储的指针(实例) 。后者由someOtherThing调用以实际调用_myFunc,这只是普通的void*。为此,首先将_myFunc强制转换回正确的类型,该类型仅在call的正文中已知。

唯一的问题是使用指向函数的指针,stub(...)调用没有内联。