Lambda捕获构造函数初始化列表中的可变参数

时间:2015-04-06 22:49:31

标签: c++ c++11 lambda functional-programming

我尝试在构造函数初始化列表中的lambda中捕获可变参数。这是一个说明问题的简单示例。

#include <functional>
#include <iostream>

void foo(int a)
{
    std::cout << a << std::endl;
}

template<typename ...Args>
class Widget
{
public:
    Widget(std::function<void(Args...)> f, Args... args)
        : _f([=]() { f(args...); })  // compiler error here
    {
    }

    void print() const { _f(); }

private:
    std::function<void()> _f;
};

int main(int argc, char* argv[])
{
    Widget<int> w(foo, 7);
    w.print();    
    return 0;
}

在VS2013中,我收到以下编译错误:

error C3546: '...' : there are no parameter packs available to expand
error C2065: 'args' : undeclared identifier

以下版本的Widget构造函数编译和工作。

Widget(std::function<void(Args...)> f, Args... args)
{
    _f = [=]() { f(args...); };
}

Widget(std::function<void(Args...)> f, Args... args)
    : _f(std::bind(f, args...))
{
}

更新: MS Visual C ++编译器团队修复了此问题,并将其包含在即将发布的Visual C ++版本中(see)。

1 个答案:

答案 0 :(得分:1)

Lambda捕获可能是编译器最终实现的C ++ 11的最后一部分,如果某个特定编译器尚未实现它,或者它的实现是错误的,那就不足为奇了。据说,gcc直到最近才得到这个权利。

典型的方法是使用元组解决这个问题。使用std::make_tuple将所有可变参数放入元组中,然后捕获元组。

然后,将元组转换回参数包。搜索stackoverflow,有几个例子说明如何做到这一点。

这会产生一大堆行李代码。但它是什么,它是什么,当编译器最终做对了,这个解决方法可以被删除,同时你会有一些有用的东西。或多或少。