如何使对模板函数的调用不那么冗长

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 模板参数与您的函数指针相匹配。