[=, this]
We propose to allow [=, this]
as a lambda capture.
With the introduction of capture-this
-by-value in C++17, it may be
desirable to increase code readability by being explicit about the kind of capture
in the presence of a [=]
-default:
By contrast, when both [=]
and [=, *this]
are present
in a code base in large numbers, it may be easy to forget that the former is different
from the latter: It is hard to notice the absence of something. In such situations, authors
may wish to be explicit and to spare the reader from having remember the correct default.
The proposal is a pure core language extension. The newly allowed syntax was previously ill-formed.
In section 8.1.5.2 [expr.prim.lambda.capture], change paragraph 2 as follows.
If a lambda-capture includes a capture-default that is &
,
no identifier in a simple-capture of that lambda-capture shall be preceded
by &
. If a lambda-capture includes a capture-default that
is =
, each simple-capture of that lambda-capture shall be of
the form “&
identifier”, “this
”,
or “* this
”. [Note: The form [&,this]
is
redundant but accepted for compatibility with ISO C++ 2014. – end note]
Ignoring appearances in initializers of init-captures, an identifier or this
shall not appear more than once in a lambda-capture. [Example:
– end example]
This proposal falls into a very crowded design space where we are left with relatively little room to move. Several alternative changes have been proposed in this space, but by and large they are all mutually exclusive. We present a few plausible alternatives, along with their advantages and disadvantages.
We will not consider deprecation in the following survey, since we are only interested in exploring the long-term direction, and deprecation without direction is not all that interesting. Everything that follows is to be understood in the context of lambdas with default captures.
0. This proposal: Allow | |
---|---|
Description: |
[&] , [&, this] , [=] , [=,
this] capture *this by reference; [&,
*this] , [=, *this] capture *this by value. |
Pros: |
|
Cons: |
|
1. Disallow | |
Description: | Remove the currently allowed redundant form [&, this] .
[&] captures *this by reference;
[&, *this] captures *this by value. |
Pros: |
|
Cons: |
|
2. Allow only | |
Description: | Remove both implicit forms [&] and [=] entirely.
[&, this] and [=, this] capture *this
by reference; [&, *this] and [=, *this] capture
*this by value. |
Pros: |
|
Cons: |
|
Note. This alternative is not viable, since there is no transition path towards it. We mention it mainly because it presents an interesting alternative reality. Moreover, if the present proposal were accepted, this would be a potential and accessible future direction. | |
3. Make | |
Description: | [=] means [=, *this] and captures *this
by value; [this, =] captures *this by reference.
|
Pros: |
|
Prons: |
|
Cons: |
|
Note. This direction is popular with several people, since it is “what lambdas should always have been like”. This change is non-atomic, and we do not wish to explore it in detail, but we note in passing that this change contains the present proposal as the non-breaking subset. |
Only alternatives 0 and 1 are immediately viable, since there is a transition path from
the current standard. Note that alternative 0 (this proposal) is a subset of and starting
point for both alternatives 2 and 3. Thus the immediate decision that is required is
between 0 and 1. We believe that allowing explicit, unambiguous code (as per 0) adds
greater value than removing redundancy from the language (as per 1). Moreover,
pragmatically, alternative 1 would perhaps struggle to ever achieve a complete removal
of [&, this]
from the language; at best the feature would end up permanently
deprecated. Without pressure to act on the deprecation, its value seems limited. By contrast,
alternative 0 enables actionable style rules to “always capture this
explicitly”, which may add real value to a codebase.
The above alternatives were surfaced during discussion on the reflector and at the BSI meeting in London. We conclude with a few further discussion points that were raised and should be heard.
[=]
is different from
[=, this]
.” (Our response: Readers may also worry whether
[=]
is different from [=, *this]
. Codebases should encourage
to always be explicit so readers do not need to worry at all.)