避免显式函子模板类型

Avoiding explicit functor template type

本文关键字:类型      更新时间:2023-10-16

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

class C {
public:
    template <typename Func>
    void foo(Func fun)
    {
        fun();
    }
};
struct S {
    void operator()() { printf ("in Sn"); }
};
....
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;
};

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

您可以使用 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;
};

这是一种手工制作的方法,可以避免将类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中,一个指向(一个instaiation)的指针,它存储在stub中。后者被someOtherThing调用来实际调用_myFunc,这只不过是普通的void*。为此,_myFunc首先被投射回正确的类型,这只有在call体内才知道。

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