我有一个简单的类 A
,它提供了一个可变函数模板。此函数使用 A
中的私有(private)数据,但函数本身是公开的。类(class)如下:
class A {
public:
A() :
_bla("bla: ") {
}
template <class T>
void bar(const T& value) {
std::cout << _bla << value << std::endl;
}
template <class H, class... T>
void bar(const H& value, const T&... data) {
std::cout << _bla << value << std::endl;
bar(data...);
}
private:
const std::string _bla;
};
在一个名为 foo.hpp 的单独文件中,我有一个函数 foo()
,它应该能够接收和使用函数 a。 bar()
作为参数:
int main(int argc, char *argv[]) {
A a;
a.bar(1, "two", 3, 4);
foo(&a.bar);
}
我不太确定从哪里开始,但我尝试了以下方法——但没有用。我怎样才能正确地做到这一点:
template <typename... T>
inline void foo(void (bar *)(const T&...)) {
unsigned int x(0), y(0), z(0);
bar(x, y, z);
}
奖励问题:有没有办法不仅调用:
foo(&a.bar);
但也可以调用 foo
并将 a.bar
绑定(bind)到一些参数,例如:
foo(&(a.bar(p1, p2));
我可以简单地将 p1
和 p2
添加到 foo
定义本身,例如:
foo(p1, p2, &a.bar);
但如果我能在之前添加这些参数,在语义上会更符合我的目的。
最佳答案
你不能在没有实例化的情况下传递函数模板的地址,因为它被视为一个完整的重载集(无论模板是否可变)。但是,您可以将它包装在一个通用仿函数中:
struct bar_caller
{
template<typename... Ts>
void operator () (A& a, Ts&&... args)
{
a.bar(std::forward<Ts>(args)...);
}
};
然后让你的函数 foo()
定义如下:
template<typename F>
inline void foo(A& a, F f) {
unsigned int x(0), y(0), z(0);
f(a, x, y, z);
}
因此您在 main()
中的函数调用将变为:
int main()
{
A a;
a.bar(1, "two", 3, 4);
foo(a, bar_caller());
}
不幸的是,目前在 C++ 中没有办法在不定义单独类的情况下轻松地将重载集包装在仿函数中 - 正如上面对 bar_caller
所做的那样。
编辑:
如果您不想将A
对象直接传递给foo()
,您仍然可以让您的bar_caller
封装对必须在其上调用函数 bar()
的 A
对象(只需注意对象的生命周期,这样您就不会使该引用悬空):
struct bar_caller
{
bar_caller(A& a_) : a(a_) { }
template<typename... Ts>
void operator () (Ts&&... args)
{
a.bar(std::forward<Ts>(args)...);
}
A& a;
};
然后您可以重写 foo()
和 main()
如下:
template<typename F>
inline void foo(F f) {
unsigned int x(0), y(0), z(0);
f(x, y, z);
}
int main()
{
A a;
a.bar(1, "two", 3, 4);
foo(bar_caller(a));
}
关于c++ - 指向可变函数模板的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16401811/