简体   繁体   中英

Can a parameter pack be captured implicitly within C++11 lambdas?

Does anyone know if the following implicit capture of 'ts' is well-formed:

template<class ... Ts> void bar(Ts ... ts) { }

template<class ... Ts> int foo(Ts ... ts) {
    auto L = [=] () {
       bar(ts...);
    };
    L();
    return 0;
}
int g = foo(1, 2, 3);

Does the standard clearly state anywhere that this should not be well formed?

14.5.3/6:

The instantiation of a pack expansion that is not a sizeof... expression produces a list E1, E2, ..., EN , where N is the number of elements in the pack expansion parameters. Each Ei is generated by instantiating the pattern and replacing each pack expansion parameter with its ith element. All of the Ei become elements in the enclosing list.

Regardless of whether you're allowed to explicitly capture a pack (you can, using [ts ...] ), the general rule of expansion will result in capture of each element of the list.

I guess it's well formed, I've not found a straight statement (the wording sometimes lacks in clarity / illustration for certain situations) but I guess it may be inferred:

§5.1.2/23:

A capture followed by an ellipsis is a pack expansion (14.5.3). [ Example:

      template<class... Args>
      void f(Args... args) {
        auto lm = [&, args...] { return g(args...); };
        lm();
      }

— end example ]

  • A capture followed by an ellipsis , implies args , in the lambda-capture , is an example of a capture (in this case, explicit), and the notable fact is that args is a parameter pack identifier . This short paragraph has the sole job of describing how lambda-captures hold pack expansions, which demonstrates parameter packs can be captured even though its purpose is not about allowing them to be captured .

§5.1.2/12:

An entity is captured if it is captured explicitly or implicitly .[...]

§3/3:

An entity is a value, object, reference, function, enumerator, type, class member, template, template specialization, namespace, parameter pack , or this.

From this I assume parameter packs are entities that can be captured explicitly or implicitly , and so, the same capturing rules as for ordinary variables shall apply, except that parameter packs shall be expanded accordingly.

I guess your question (and the same argumentation) could be applied equally well for reference variables for example ( It is unspecified whether or not a reference requires storage. §8.3.2/4 ). It seems you're interested when you're allowed or not to refer to a parameter pack identifier inside a lambda.

You can think the same about reference variables in the outer scope since you may have access to them but couldn't even be allowed to access the identifier of the original variable.

They're as ethereal as parameter packs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM