说我有一个模板:
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);
答案 0 :(得分:1)
不,这是不可能的。
有用的解决方法的确切性质取决于问题的性质,但它很可能涉及std::function
和std::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}}进入它。std::bind(&SomeClass::memberfunction, SomeObject)
T
foo
个{{1}}参数的公共基类。如果您的需求超出了这个范围,那么您正在尝试扩展C ++类型系统的限制,并且应该重新考虑您的设计。