假设我有一个模板:
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);
最佳答案
不,这不可能。
有用解决方法的确切性质取决于问题的性质,但很可能涉及 std::function
和 std::bind
(或 lambda)。一般而言,诀窍通常是重写 foo
以这样一种方式,它不必关心绑定(bind)到它的函数类型(这就是 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
不能根据公共(public)基类中的模板参数提供接口(interface)。那么剩下两个选项:
- 如果要调用该函数的对象可以与该函数同时绑定(bind),则可以生成
foo
。一个类,让它存储一个std::function<void()>
并推一个std::bind(&SomeClass::memberfunction, SomeObject)
- 否则,如果没有非常邪恶的 hackery,您将获得的最好结果就是将自己限制在一个共同的基类中,该基类本来是
T
。foo
的参数.
如果您的需求超出此范围,您就是在试图突破 C++ 类型系统的限制,您应该重新考虑您的设计。
关于c++ - 将函数传递给方法原型(prototype),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27624961/