如果我有一个采用 lambda 表达式的模板化函数,我该如何专门化它,以便它可以处理采用不同数量参数的 lambda 表达式?以下代码有效:
template<typename Lambda>
void doSomething(Lambda callback)
{
callback();
}
doSomething([] () { /* some code here */ } );
但如果我也想这样调用它:
doSomething([&foo] (int x) { /* some code here */ } );
doSomething([&foo] (int x, int y) { /* some code here */ } );
我使用什么语法来提供 doSomething() 的特殊版本?此语法:
template<>
void doSomething<[] (int)>([] (int) callback)
{
callback(3);
}
无法在 Visual Studio 2012 下编译,而且我无法找到任何关于有效语法的引用资料。是否可以 ?或者,是否可以从 doSomething() 内部判断提供的回调需要多少参数,以便我可以执行如下操作:
template<typename Lambda>
void doSomething(Lambda callback)
{
int numArgs = ???
switch (numArgs) {
case 0: callback(); break;
case 1: callback(1); break;
case 2: callback(1,2); break;
}
}
最佳答案
lambda 有两种情况:捕获时和不捕获时。
对于第一种情况,需要提取lambda的返回类型和参数类型(从lambda的operator()
),在this question中有介绍.
对于最后一种情况,您可以使用函数指针特化,因为非捕获 lambda 具有函数指针转换运算符。
关于您的 doSomething()
函数,不可能像您在此处所做的那样根据推导的参数数量直接调用仿函数:
template<typename Lambda>
void doSomething(Lambda callback)
{
int numArgs = ???
switch (numArgs)
{
case 0: callback(); break;
case 1: callback(1); break;
case 2: callback(1,2); break;
}
}
(所需的特性是 static if
并且已被提议用于下一个 C++ 标准,请参阅 n3322 和 n3329)
您需要使用专门针对特定函数签名的辅助函数或结构。像这样的东西:
template<typename T> struct helper {};
template<typename R, typename P1>
struct helper<R(P1)>
{
static R call(R (*lambda)(P1)) { return lambda(magic_param); }
};
template<typename R, typename P1, typename P2>
struct helper<R(P1,P2)>
{
static R call(R(*lambda)(P1,P2)) { return lambda(magic_param_1,magic_param_2); }
};
// ...
template<typename R, typename... A>
void doSomething(R (*callback)(A...))
{
helper<R(A...)>::call(callback);
}
这带来了一个重要的问题:您将如何生成参数 (magic_param...
)?
关于c++ - 是否可以根据 lambda 采用的参数数量专门化采用 lambda 表达式的模板函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13295935/