将lambda应用于模板参数包;没有捕获lambda参数

时间:2015-02-20 10:07:28

标签: c++ c++11 variadic-templates

我想编写一个函数来接受任意数量的数字参数并返回它们的均值。使用Wikipedia的扩展技巧:

namespace detail
{
    template<typename... Args> void iterate_template_pack(Args&&...) {}
}

template <typename ResultType, typename... Args>
ResultType arithmeticMean(Args&&... args)
{
    ResultType acc = ResultType(0);
    size_t n = 0;

    detail::iterate_template_pack(([&](){
        acc += ResultType(args);
        ++n;
    })...);

    return acc / n;
}

这编译并且几乎可以工作:我可以正确地看到lambda接收args。但是,accn不会被修改。怎么样?

1 个答案:

答案 0 :(得分:4)

你需要调用lambda,否则你只是将一系列lambda对象传递给iterate_template_pack

detail::iterate_template_pack(([&](){
    acc += ResultType(args);
    ++n;
})()...);
  ^^

由于你的lambda没有返回值,你还需要提供一个传递给iterate_template_pack的值,因为你不能将void作为参数传递:

detail::iterate_template_pack((([&](){
    acc += ResultType(args);
    ++n;
})(), void(), 0)...);

From Wikipedia(我的重点):

  

可以指定一个lambda表达式并执行就地,而不是执行一个函数,这样就可以就地执行任意语句序列。

pass{([&]{ std::cout << args << std::endl; }(), 1)...};

请注意,由于PR 47226,gcc无法编译上述内容(另请参阅https://stackoverflow.com/a/13444602/34509)。一种解决方法是在lambda:

之外扩展参数包
detail::iterate_template_pack((([&](ResultType&& r){
    acc += r;
    ++n;
}(args)), void(), 0)...);