Can `this` be captured by reference?

57 views
Skip to first unread message

Brian Bi

unread,
Jul 22, 2015, 8:19:22 PM7/22/15
to std-dis...@isocpp.org
It seems that if `this` is implicitly captured and the capture-default is `&`, then `this` is captured by reference, according to the direct wording of the standard:

An entity is captured by copy if it is implicitly captured and the capture-default is `=` or if it is explicitly captured with a capture that is not of the form `&` identifier or `&` identifier initializer.

An entity is captured by reference if it is implicitly or explicitly captured but not captured by copy. 

Yet, capturing `this` by reference does not make much sense since `this` is a prvalue. The following quotes also from the standard, taken together, also seem to imply in a roundabout way that `this` is supposed to always be captured by copy

For each entity captured by copy, an unnamed non-static data member is declared in the closure type.

It is unspecified whether additional unnamed non-static data members are declared in the closure type for entities captured by reference. 

If `this` is captured, each odr-use of `this` is transformed into an access to the corresponding unnamed data member of the closure type, cast (5.4) to the type of `this`.

Consider this code, that gcc and clang both accept: http://coliru.stacked-crooked.com/a/d1c56761309e6f4a

The standard seems to allow this; there's no rule I can find that says it's not allowed.

I wonder whether the intent was that `this` is captured by copy even if the capture-default is `&`?

--
Brian Bi

Thiago Macieira

unread,
Jul 23, 2015, 2:37:15 AM7/23/15
to std-dis...@isocpp.org
On Wednesday 22 July 2015 17:19:19 Brian Bi wrote:
> Yet, capturing `this` by reference does not make much sense since `this` is
> a prvalue. The following quotes also from the standard, taken together,
> also seem to imply in a roundabout way that `this` is supposed to always be
> captured by copy
>
> > For each entity captured by copy, an unnamed non-static data member is
> > declared in the closure type.
> >
> > It is unspecified whether additional unnamed non-static data members are
> > declared in the closure type for entities captured by reference.
> >
> > If `this` is captured, each odr-use of `this` is transformed into an
> > access
> > to the corresponding unnamed data member of the closure type, cast (5.4)
> > to
> > the type of `this`.
>
> Consider this code, that gcc and clang both accept:
> http://coliru.stacked-crooked.com/a/d1c56761309e6f4a
>
> The standard seems to allow this; there's no rule I can find that says it's
> not allowed.
>
> I wonder whether the intent was that `this` is captured by copy even if the
> *capture-default* is `&`?

I'd say so. I don't think no one is advocating copying the enclosing object.

I'd say the interesting questions would be:

a) is x captured by copy? Or is the this pointer captured? In other words, if
the enclosing object changes the value of x between the lambda creation and
the call, will the returned value update?

b) in a capture defaulting to copy, is the this pointer pointing to a const
object? In other words, is this allowed:

auto l = [] { x++; };

Because if it were called "that" instead of "this", it would be allowed:

void f(S *that)
{
auto l = [that] { that->x++; }
}
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358

Edward Catmur

unread,
Jul 23, 2015, 5:04:14 AM7/23/15
to ISO C++ Standard - Discussion, thi...@macieira.org
On Thursday, 23 July 2015 07:37:15 UTC+1, Thiago Macieira wrote:
a) is x captured by copy? Or is the this pointer captured? In other words, if
the enclosing object changes the value of x between the lambda creation and
the call, will the returned value update?

Only automatic variables and this can be captured implicitly. [expr.prim.lambda]/12: A lambda-expression with an associated capture-default that does not explicitly capture this or a variable with automatic storage duration [...] is said to implicitly capture the entity (i.e., this or a variable) [...]
 
b) in a capture defaulting to copy, is the this pointer pointing to a const
object? In other words, is this allowed:

    auto l = [] { x++; };

this has the same type (and thus cv-qualification) it has in the enclosing scope. So yes, modifying members of the object is allowed. (You missed out the capture-default).

Given that clang, gcc and MSVC all allow odr-usage of this regardless of the capture-default (as long as it is present) I'd argue that we're just missing a small addition to say that implicit capture of this is always by value. As Brian observed, the language on odr-use of this assumes that this is always captured by copy. Note btw that the grammar excludes &this as a simple-capture, so explicit capture of this is already always by copy.

Suggestion:

An entity is captured by copy if it is implicitly captured and _either it is this or_ the capture-default is = or if it is explicitly captured with a capture that is not of the form & identifier or & identifier initializer.

Alternative (more verbose but possibly clearer):

An entity _other than this_ is captured by copy if it is implicitly captured and the capture-default is = or if it is explicitly captured with a capture that is not of the form & identifier or & identifier initializer. _this is captured by copy if it is implicitly or explicitly captured._

I can't find a DR on this. There's no implementation variance so it should uncontroversial to submit one - Brian?

Brian Bi

unread,
Jul 23, 2015, 2:40:24 PM7/23/15
to std-dis...@isocpp.org, thi...@macieira.org
Yeah, I'll submit it as a DR.

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussio...@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-discussion/.



--
Brian Bi
Reply all
Reply to author
Forward
0 new messages