4

我在玩函子。我正在使用下面的标准示例:

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;
};

我现在需要将整个班级设为模板吗?如果是这样,编译器是否可以像使用单个函子一样推断模板类型,还是我必须显式提供它?谢谢。

4

2 回答 2

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;
};
于 2013-09-18T10:58:57.573 回答
-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(...)调用。

于 2013-09-18T11:12:41.957 回答