c++ - 是否可以根据 lambda 采用的参数数量专门化采用 lambda 表达式的模板函数?

标签 c++ templates c++11 lambda

如果我有一个采用 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++ 标准,请参阅 n3322n3329)

您需要使用专门针对特定函数签名的辅助函数或结构。像这样的东西:

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/

相关文章:

c++ - 一个一个地传递参数,或者将它们包装在一个数组、结构体或元组中

c++ - 尖括号与圆括号中的非类型名称参数

c++ - 在循环中创建和填充 vector

c++ - 为什么 std::function 太慢是因为 CPU 无法利用指令重新排序?

c++ - 访问 XMMatrix 的 float - () 运算符不起作用

c++ - 如何使用 boost::iostreams 管道进入 std::cout

C++ 如何将 std::vector<Derived*> 类型的指针设置为 std::vector<Base*> 类型的对象

c++ - 我可以为模板成员函数提供多个默认值吗?

c++ - 收集不同类型的类并在 C++ 中调用它们的方法

c++11 - 用户定义的字符串文字的长度作为模板参数?