如何使对模板函数的调用不那么冗长
How to make a call to a template function less verbose
有函数
template <class ...T>
void foo(std::function<void(T...)> callback);
我向其中传递回调。
我想做类似的事情
foo(bar);
其中 bar
例如,
void bar(int a, long b, double c, float d);
但这给了我
error: no matching function for call to bar(void (&)(int, long int, double, float))
我必须将 foo
称为
foo(std::function<void(int, long, double, float)>(bar));
太冗长了。甚至
foo<int, long, double, float>(bar);
会更好。
foo(bar);
会很理想。
无论如何,我怎样才能使对 foo
的调用不那么冗长?
编辑: foo
的声明必须保持不变。
如果您的 foo
定义不是一成不变的,可以将其更改为
#include <functional>
template <class Ret, class ...T>
void foo(Ret callback(T... params))
{
}
void bar(int a, long b, double c, float d){}
int main()
{
foo(bar);
}
我会编写一个包装函数,将函数指针转换为 std::function
包装器:
template <typename... T>
void foo(std::function<void (T...)> f) {}
template <typename... T>
void foo(void (*f)(T...)) {
foo(std::function<void (T...)>(f));
}
foo()
可以这样调用:
void bar(int,double) {}
void foo_caller() {
foo(std::function<void (int,double)>(bar));
foo(bar);
}
附录:非静态成员函数包装器
相同的方法可用于指向成员函数的指针——只需添加另一个重载:
template <typename C,typename... T>
void foo(void (C::*f)(T...)) {
foo(std::function<void (C *,T...)>(f));
}
注意成员函数的 this
指针的额外第一个参数。用法类似:
struct quux {
void mf(char *,double) {}
};
void foo_caller() {
foo(&quux::mf);
}
如果您知道您将传递一个普通的 函数指针 到 foo
,而不仅仅是任何 C++11 lambda,您可以重新定义 foo
如:
template <class ...T>
void foo(void(*callback)(T...)) {
// .....
}
如果你想支持 lambda,你可以使用更通用的类型
template <class LambdaType>
void foo(LambdaType callback) {
// .....
}
这种方法的缺点是,如果您传递的不是函数或 lambda 的东西,您会从 foo
.
内部收到奇怪的模板错误消息
使用您的原始解决方案,编译器在将 T...
匹配到 int, long, double, float
时遇到问题,可能是因为它是嵌套类型。
如果我告诉你将 void(int, double)
匹配到 MyTempalte<T...>
你不会知道我打算用 int, double
替换 T...
,因为你不知道MyTemplate
对其参数做了什么。也许 MyTemplate
首先对其模板参数做了一些奇怪的事情?
同样,编译器不知道如何将 std::function
模板参数与您的函数指针相匹配。
有函数
template <class ...T>
void foo(std::function<void(T...)> callback);
我向其中传递回调。
我想做类似的事情
foo(bar);
其中 bar
例如,
void bar(int a, long b, double c, float d);
但这给了我
error: no matching function for call to bar(void (&)(int, long int, double, float))
我必须将 foo
称为
foo(std::function<void(int, long, double, float)>(bar));
太冗长了。甚至
foo<int, long, double, float>(bar);
会更好。
foo(bar);
会很理想。
无论如何,我怎样才能使对 foo
的调用不那么冗长?
编辑: foo
的声明必须保持不变。
如果您的 foo
定义不是一成不变的,可以将其更改为
#include <functional>
template <class Ret, class ...T>
void foo(Ret callback(T... params))
{
}
void bar(int a, long b, double c, float d){}
int main()
{
foo(bar);
}
我会编写一个包装函数,将函数指针转换为 std::function
包装器:
template <typename... T>
void foo(std::function<void (T...)> f) {}
template <typename... T>
void foo(void (*f)(T...)) {
foo(std::function<void (T...)>(f));
}
foo()
可以这样调用:
void bar(int,double) {}
void foo_caller() {
foo(std::function<void (int,double)>(bar));
foo(bar);
}
附录:非静态成员函数包装器
相同的方法可用于指向成员函数的指针——只需添加另一个重载:
template <typename C,typename... T>
void foo(void (C::*f)(T...)) {
foo(std::function<void (C *,T...)>(f));
}
注意成员函数的 this
指针的额外第一个参数。用法类似:
struct quux {
void mf(char *,double) {}
};
void foo_caller() {
foo(&quux::mf);
}
如果您知道您将传递一个普通的 函数指针 到 foo
,而不仅仅是任何 C++11 lambda,您可以重新定义 foo
如:
template <class ...T>
void foo(void(*callback)(T...)) {
// .....
}
如果你想支持 lambda,你可以使用更通用的类型
template <class LambdaType>
void foo(LambdaType callback) {
// .....
}
这种方法的缺点是,如果您传递的不是函数或 lambda 的东西,您会从 foo
.
使用您的原始解决方案,编译器在将 T...
匹配到 int, long, double, float
时遇到问题,可能是因为它是嵌套类型。
如果我告诉你将 void(int, double)
匹配到 MyTempalte<T...>
你不会知道我打算用 int, double
替换 T...
,因为你不知道MyTemplate
对其参数做了什么。也许 MyTemplate
首先对其模板参数做了一些奇怪的事情?
同样,编译器不知道如何将 std::function
模板参数与您的函数指针相匹配。