<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    GB15: Issue 2011 resolution
   </TITLE>
</HEAD>
<BODY>
<TABLE ALIGN="RIGHT" CELLSPACING="0" CELLPADDING="0">
<TR><TD ALIGN="RIGHT"><B>Document:&#160;&#160;&#160;</B></TD><TD>WG21 P0613R0</TD></TR>
<TR><TD ALIGN="RIGHT"><B>Audience:&#160;&#160;&#160;</B></TD><TD>WG21</TD></TR>
<TR><TD ALIGN="RIGHT" VALIGN="TOP"><B>Author:&#160;&#160;&#160;</B></TD>
<TD>William M. (Mike) Miller<BR>Edison Design Group, Inc.<BR>
<TT>wmm@edg.com</TT></TD></TR>
<TR><TD ALIGN="RIGHT"><B>Date:&#160;&#160;&#160;</B></TD><TD>2017-02-27</TD></TR>
</TABLE><BR><BR><BR><BR><BR>

<H1>NB comment GB15: Resolution of Core Issue 2011</H1>

<HR><A NAME="2011"></A><H4>2011.
  
Unclear effect of reference capture of reference
</H4><B>Section: </B>5.1.5&#160; [expr.prim.lambda]
 &#160;&#160;&#160;

 <B>Status: </B>review
 &#160;&#160;&#160;

 <B>Submitter: </B>Ville Voutilainen
 &#160;&#160;&#160;

 <B>Date: </B>2014-09-28
  &#160;&#160;&#160;
  <B>Drafting: </B>Miller<BR>


<committee_only><P>(From messages <A href="
   http://accu.org/cgi-bin/wg21/message?wg=core&amp;msg=25953">25953</A>, <A href="
   http://accu.org/cgi-bin/wg21/message?wg=core&amp;msg=25956">25956</A>, 
<A href="
   http://accu.org/cgi-bin/wg21/message?wg=core&amp;msg=25958">25958</A> through <A href="
   http://accu.org/cgi-bin/wg21/message?wg=core&amp;msg=25960">25960</A>, <A href="
   http://accu.org/cgi-bin/wg21/message?wg=core&amp;msg=25962">25962</A>, and
<A href="
   http://accu.org/cgi-bin/wg21/message?wg=core&amp;msg=25964">25964</A>.)</P></committee_only>

<P>The Standard refers to capturing &#8220;entities,&#8221; and a
reference is an entity.  However, it is not clear what capturing a
reference by reference would mean.  In particular, 5.1.5 [expr.prim.lambda]
paragraph 16 says,</P>

<BLOCKQUOTE>

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

</BLOCKQUOTE>

<P>If a reference captured by reference is not represented by a
member, it is hard to see how something like the following
example could work:</P>

<PRE>
  #include &lt;functional&gt;
  #include &lt;iostream&gt;

  std::function&lt;void()&gt; make_function(int&amp; x) {
    return [&amp;]{ std::cout &lt;&lt; x &lt;&lt; std::endl; };
  }

  int main() {
    int i = 3;
    auto f = make_function(i);
    i = 5;
    f();
  }
</PRE>

<P>Should this be undefined behavior or should it print <TT>5</TT>?</P>

<P><B>Proposed resolution (November, 2014) [SUPERSEDED]:</B></P>

<OL><LI><P>Change 5.1.5 [expr.prim.lambda] paragraph 18 as follows:</P></LI>

<BLOCKQUOTE>

<P>Every <I>id-expression</I> within
the <I>compound-statement</I> of a <I>lambda-expression</I>
that is an odr-use (3.2 [basic.def.odr]) of an entity captured by copy is
transformed into an access to the corresponding unnamed data
member of the closure type. [<I>Note:</I>
An <I>id-expression</I> that is not an odr-use refers to the
original entity, never to a member of the closure
type. Furthermore, such an <I>id-expression</I> does not
cause the implicit capture of the entity.  &#8212;<I>end
note</I>] If <TT>this</TT> is captured, each odr-use
of <TT>this</TT> is transformed into an access to the
corresponding unnamed data member of the closure type, cast
(5.4 [expr.cast]) to the type of <TT>this</TT>. [<I>Note:</I> The cast
ensures that the transformed expression is a
prvalue. &#8212;<I>end
note</I>] <SPAN style="font-weight:bold;background-color:#A0FFA0">An <I>id-expression</I> within
the <I>compound-statement</I> of a <I>lambda-expression</I>
that is an odr-use of a reference captured by reference
refers to the entity to which the captured reference is
bound and not to the captured reference. [<I>Note:</I> Such
odr-uses are not invalidated by the end of the captured
reference's lifetime. &#8212;<I>end note</I>]</SPAN>
[<I>Example:</I></P>

<PRE>
  void f(const int*);
  void g() {
    const int N = 10;
    [=] {
    int arr[N]; //<SPAN style="font-family:Times;font-style:italic"> OK: not an odr-use, refers to automatic variable</SPAN>
    f(&amp;N);      //<SPAN style="font-family:Times;font-style:italic"> OK: causes </SPAN>N<SPAN style="font-family:Times;font-style:italic"> to be captured; </SPAN>&amp;N<SPAN style="font-family:Times;font-style:italic"> points to the</SPAN>
                //<SPAN style="font-family:Times;font-style:italic"> corresponding member of the closure type</SPAN>
    };
  }
<SPAN style="font-weight:bold;background-color:#A0FFA0">  auto h(int &amp;r) {
    return [&amp;]() {
      ++r;      //<SPAN style="font-family:Times;font-style:italic"> Valid after </SPAN>h<SPAN style="font-family:Times;font-style:italic"> returns if the lifetime of the</SPAN>
                //<SPAN style="font-family:Times;font-style:italic"> object to which </SPAN>r<SPAN style="font-family:Times;font-style:italic"> is bound has not ended</SPAN>
    };
  }</SPAN>
</PRE>

<P>&#8212;<I>end example</I>]</P>

</BLOCKQUOTE>

<LI><P>Change 5.1.5 [expr.prim.lambda] paragraph 23 as follows:</P></LI>

<BLOCKQUOTE>

[<I>Note:</I> If <SPAN style="text-decoration:line-through;background-color:#FFA0A0">an</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">a non-reference</SPAN> entity is
implicitly or explicitly captured by reference, invoking the function call
operator of the corresponding <I>lambda-expression</I> after the lifetime
of the entity has ended is likely to result in undefined
behavior. &#8212;<I>end note</I>]

</BLOCKQUOTE>

</OL>

<P><B>Proposed resolution (February, 2017):</B></P>

<OL><LI><P>Change 5.1.5 [expr.prim.lambda] paragraph 17 as follows:</P></LI>

<BLOCKQUOTE>

<P>Every <I>id-expression</I> within the <I>compound-statement</I> of
a <I>lambda-expression</I> that is an odr-use (3.2 [basic.def.odr]) of
an entity captured by copy is transformed into an access to the
corresponding unnamed data member of the closure type. [<I>Note:</I>
An <I>id-expression</I> that is not an odr-use refers to the original
entity, never to a member of the closure type. Furthermore, such
an <I>id-expression</I> does not cause the implicit capture of the entity.
&#8212;<I>end note</I>] If <TT>*this</TT> is captured by copy, each odr-use
of <TT>this</TT> is transformed into a pointer to the corresponding unnamed
data member of the closure type, cast (5.4 [expr.cast]) to the
type of <TT>this</TT>. [<I>Note:</I> The cast ensures that the transformed
expression is a prvalue. &#8212;<I>end
note</I>] <SPAN style="font-weight:bold;background-color:#A0FFA0">An <I>id-expression</I> within the <I>compound-statement</I>
of a <I>lambda-expression</I> that is an odr-use of a reference captured by
reference refers to the entity to which the captured reference is bound and
not to the captured reference. [<I>Note:</I> The validity of such
captures is determined by the lifetime of the object to which the
reference refers, not by the lifetime of the reference
itself. &#8212;<I>end note</I>]</SPAN> [<I>Example:</I></P>

<PRE>
  void f(const int*);
  void g() {
    const int N = 10;
    [=] {
    int arr[N]; //<SPAN style="font-family:Times;font-style:italic"> OK: not an odr-use, refers to automatic variable</SPAN>
    f(&amp;N);      //<SPAN style="font-family:Times;font-style:italic"> OK: causes </SPAN>N<SPAN style="font-family:Times;font-style:italic"> to be captured; </SPAN>&amp;N<SPAN style="font-family:Times;font-style:italic"> points to the</SPAN>
                //<SPAN style="font-family:Times;font-style:italic"> corresponding member of the closure type</SPAN>
    };
  }
<SPAN style="font-weight:bold;background-color:#A0FFA0">  auto h(int &amp;r) {
    return [&amp;] {
      ++r;      //<SPAN style="font-family:Times;font-style:italic"> Valid after </SPAN>h<SPAN style="font-family:Times;font-style:italic"> returns if the lifetime of the</SPAN>
                //<SPAN style="font-family:Times;font-style:italic"> object to which </SPAN>r<SPAN style="font-family:Times;font-style:italic"> is bound has not ended</SPAN>
    };
  }</SPAN>
</PRE>

<P>&#8212;<I>end example</I>]</P>

</BLOCKQUOTE>

<LI><P>Change 5.1.5 [expr.prim.lambda] paragraph 25 as follows:</P></LI>

<BLOCKQUOTE>

[<I>Note:</I> If <SPAN style="text-decoration:line-through;background-color:#FFA0A0">an</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">a non-reference</SPAN> entity is
implicitly or explicitly captured by reference, invoking the function call
operator of the corresponding <I>lambda-expression</I> after the lifetime
of the entity has ended is likely to result in undefined
behavior. &#8212;<I>end note</I>]

</BLOCKQUOTE>

</OL>

<BR><BR></BODY>
</HTML>
