Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generalized lambda capture on param-pack?

In C++14, generalized lambda capture let us do:

template<class T>
auto pack(T t)
{
    return [t=std::move(t)](auto&& f){f(t);};
};

But it doesn't play with param-pack:

template<class... T>
auto pack(T... t)
{
    return [t=std::move(t)...](auto&& f){f(t...);};
};

Is there any special syntax or further standard proposal to address this?

like image 797
Jamboree Avatar asked Jul 18 '14 02:07

Jamboree


People also ask

What does it mean to lambda capture this?

The lambda is capturing an outside variable. A lambda is a syntax for creating a class. Capturing a variable means that variable is passed to the constructor for that class. A lambda can specify whether it's passed by reference or by value.

How do you pass a lambda function in C++?

Permalink. All the alternatives to passing a lambda by value actually capture a lambda's address, be it by const l-value reference, by non-const l-value reference, by universal reference, or by pointer.

Does lambda capture reference by value?

Lambdas always capture objects, and they can do so by value or by reference.

What is lambda function in C++11?

C++11 introduces lambdas allow you to write an inline, anonymous functor to replace the struct f . For small simple examples this can be cleaner to read (it keeps everything in one place) and potentially simpler to maintain, for example in the simplest form: void func3(std::vector<int>& v) { std::for_each(v.


1 Answers

My draft of C++14 says ([expr.prim.lambda]/24):

A simple-capture followed by an ellipsis is a pack expansion (14.5.3). An init-capture followed by an ellipsis is ill-formed.

So it looks like there is no way to do a variadic generalized capture. A possible workaround is to just capture the arguments in a tuple and then use one of the solutions suggested here: "unpacking" a tuple to call a matching function pointer

auto pack(T... t)
{
    return [args=make_tuple(std::move(t)...)](auto&& f){
               // find a way to call f with args
           };
};

EDIT:

It's now voted into C++20, made by this proposal. Although the syntax is a bit different:

template<class... T>
auto pack(T... t)
{
    return [...t=std::move(t)](auto&& f){f(t...);};
};

Note that the ... is before the init-capture.

like image 140
Brian Bi Avatar answered Oct 04 '22 02:10

Brian Bi