将函数传递给方法原型

时间:2014-12-23 17:10:16

标签: c++ templates function-pointers member-function-pointers

说我有一个模板:

template <typename T>
class foo{
    void (T::bar*)(int);
public:
    void setMethod(void (T::*)(int) f)
};

有没有办法在这个模板中使用非成员函数?

我试过了:

  • foo<void>().setMethod(&func);
  • foo<nullptr_t>().setMethod(&func);

1 个答案:

答案 0 :(得分:1)

不,这是不可能的。

有用的解决方法的确切性质取决于问题的性质,但它很可能涉及std::functionstd::bind(或lambdas)。一般来说,诀窍通常是以这样的方式重写foo,使得它不必关心绑定到它的函数的类型(这是std::function的用途)。

可以采取的一种方法是

template <typename T>
class foo{
public:
  // Here we do not care about the type of function we're binding
  template<typename Func>
  void  setMethod(Func f) { func_ = f; }

  void callMethod(T &obj) { func_(obj); }

private:
  // only about its signature
  std::function<void(T&)> func_;
};

给定类型

struct A {
  void foo();
  void bar(int);
};

和一个功能

void qux(A &);

以后可以做任何

Foo<A> f;

f.setMethod(&A::foo);
f.setMethod(qux);
f.setMethod(std::bind(&A::bar, std::placeholders::_1, 2));
f.setMethod([](A &obj) { obj.foo(); });

或者确实用setMethod接受operator()的任何内容来致电A&

如果需要Liskov替换(OP的情况),这将不起作用,因为foo不能提供接口,具体取决于公共基类中的模板参数。然后还有两个选择:

  • 如果要调用函数的对象可以与函数同时绑定,则可以使foo成为一个类,让它存储std::function<void()>并推送{ {1}}进入它。
  • 否则,在没有非常邪恶的hackery的情况下,你将获得最好的结果是将自己局限于std::bind(&SomeClass::memberfunction, SomeObject) T foo个{{1}}参数的公共基类。

如果您的需求超出了这个范围,那么您正在尝试扩展C ++类型系统的限制,并且应该重新考虑您的设计。