<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    Core "ready" Issues
   </TITLE>
</HEAD>
<BODY>
<TABLE ALIGN="RIGHT" CELLSPACING="0" CELLPADDING="0">
<TR>
<TD ALIGN="RIGHT">
      Document number:
     </TD>
<TD>
       &#160;P1358R0</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Date:
     </TD>
<TD>
      &#160;2019-02-22</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Project:
     </TD>
<TD>
      &#160;Programming Language C++
     </TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Reference:
     </TD>
<TD>
      &#160;ISO/IEC IS 14882:2017
     </TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Reply to:
     </TD>
<TD>
      &#160;William M. Miller
     </TD>
</TR>
<TR>
<TD></TD>
<TD>
      &#160;Edison Design Group, Inc.
     </TD>
</TR>
<TR>
<TD></TD>
<TD>
      &#160;<A HREF="mailto://wmm@edg.com">wmm@edg.com</A></TD>
</TR>
</TABLE><BR CLEAR="ALL"><BR><CENTER>
<H2>
     Core Language Working Group "ready" Issues
     for the
     February, 2019 (Kona) meeting
    </H2>
</CENTER><BR><P>
    References in this document reflect the section and paragraph
    numbering of document
    <A HREF="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4778.pdf">WG21 N4778</A>.
   </P>
<HR><A NAME="2256"></A><H4>2256.
  
Lifetime of trivially-destructible objects
</H4><B>Section: </B>6.6.3&#160; [basic.life]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2016-03-30




<P>According to 6.4 [basic.lookup] bullet 1.4, the following example
has defined behavior because the lifetime of <TT>n</TT> extends until its
storage is released, which is after <TT>a</TT>'s destructor runs:</P>

<PRE>
  void f() { 
    struct A { int *p; ~A() { *p = 0; } } a; 
    int n; 
    a.p = &amp;n; 
  } 
</PRE>

<P>It would be more consistent if the end of the lifetime of all objects,
regardless of whether they have a non-trivial destructor, were treated
the same.</P>

<P><B>Notes from the March, 2018 meeting:</B></P>

<P>CWG agreed with the suggested direction.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<OL><LI><P>Change 6.6.3 [basic.life] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

<P>The <I>lifetime</I> of an object or reference is a runtime
property of the object or reference. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">An object is said
to have <I>non-vacuous initialization</I> if it is of a
class or array type and it or one of its subobjects is
initialized by a constructor other than a trivial default
constructor. [<I>Note:</I> : Initialization by a trivial
copy/move constructor is non-vacuous
initialization. &#8212;<I>end note</I>]</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">A variable is said to have <I>vacuous
initialization</I> if it is default-initialized and, if it
is of class type or (possibly multi-dimensional) array
thereof, that class type has a trivial default
constructor.</SPAN> The lifetime of an object of
type <TT>T</TT> begins when:</P>

<UL><LI><P>storage with the proper alignment and size for
type <TT>T</TT> is obtained, and</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">if the object has non-vacuous
initialization,</SPAN> its initialization <SPAN style="font-weight:bold;background-color:#A0FFA0">(if any)</SPAN>
is
complete <SPAN style="font-weight:bold;background-color:#A0FFA0">(including vacuous initialization)
(9.3 [dcl.init]</SPAN>,</P></LI>

</UL>

<P>except that if the object is a union member or subobject
thereof, its lifetime only begins if that union member is
the initialized member in the union
(9.3.1 [dcl.init.aggr], 10.9.2 [class.base.init]),
or as described in 10.4 [class.union]. The lifetime
of an object <I>o</I> of type <TT>T</TT> ends when:</P>

<UL><LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">if <TT>T</TT> is a non-class type, the object
is destroyed, or</SPAN></P></LI>

<LI><P>if <TT>T</TT> is a class type <SPAN style="text-decoration:line-through;background-color:#FFA0A0">with a non-trivial
destructor (10.3.6 [class.dtor])</SPAN>, the destructor
call starts, or</P></LI>

<LI><P>the storage which the object occupies is released, or is
reused by an object that is not nested within <I>o</I>
(6.6.2 [intro.object]).</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 6.8.3.4 [basic.start.term] paragraphs 1 and 2 as
follows:</P></LI>

<BLOCKQUOTE>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">Destructors (10.3.6 [class.dtor]) for initialized</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">Constructed</SPAN>
objects (<SPAN style="text-decoration:line-through;background-color:#FFA0A0">that is, objects whose lifetime
(6.6.3 [basic.life]) has begun</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">9.3 [dcl.init]</SPAN>) with static storage
duration<SPAN style="text-decoration:line-through;background-color:#FFA0A0">,</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">are destroyed</SPAN> and functions
registered with <TT>std::atexit</TT><SPAN style="text-decoration:line-through;background-color:#FFA0A0">,</SPAN> are called
as part of a call to <TT>std::exit</TT>
(16.5 [support.start.term]).  The call to <TT>std::exit</TT>
is sequenced before the <SPAN style="text-decoration:line-through;background-color:#FFA0A0">invocations of the destructors</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">destructions</SPAN> and the registered functions.
[<I>Note:</I> Returning from <TT>main</TT>
invokes <TT>std::exit</TT>
(6.8.3.1 [basic.start.main]). &#8212;<I>end note</I>]</P>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">Destructors for initialized</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">Constructed</SPAN> objects with thread storage duration
within a given thread
are <SPAN style="text-decoration:line-through;background-color:#FFA0A0">called</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">destroyed</SPAN> as a result of
returning from the initial function of that thread and as a
result of that thread
calling <TT>std::exit</TT>. The <SPAN style="text-decoration:line-through;background-color:#FFA0A0">completions of the
destructors for</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">destruction of</SPAN>
all <SPAN style="text-decoration:line-through;background-color:#FFA0A0">initialized</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">constructed</SPAN> objects
with thread storage duration within that thread strongly
happen<SPAN style="font-weight:bold;background-color:#A0FFA0">s</SPAN> before <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the initiation of the
destructors of</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">destroying</SPAN> any object with
static storage duration.</P>

</BLOCKQUOTE>

<LI><P>Change 8.6 [stmt.jump] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

...[<I>Note:</I> However, the program can be terminated (by
calling std::exit() or std::abort()
(16.5 [support.start.term]), for example) without destroying
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">class</SPAN> objects with automatic storage
duration. &#8212;<I>end note</I>]

</BLOCKQUOTE>

<LI><P>Change 8.7 [stmt.dcl] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

It is possible to transfer into a block, but not in a way
that bypasses declarations with initialization (including
ones in <I>condition</I>s and <I>init-statement</I>s). A program
that jumps<SUP>92</SUP> from a point where a
variable with automatic storage duration is not in scope to
a point where it is in scope is ill-formed unless the
variable has <SPAN style="text-decoration:line-through;background-color:#FFA0A0">scalar type, class type with a trivial default
constructor and a trivial destructor, a cv-qualified version
of one of these types, or an array of one of the preceding
types and is declared without an <I>initializer</I></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">vacuous initialization</SPAN>
(9.3 [dcl.init]). <SPAN style="font-weight:bold;background-color:#A0FFA0">In such a case, the variables with
vacuous initialization are constructed in the order of their
declaration.</SPAN> [<I>Example:</I>...

</BLOCKQUOTE>

<LI><P>Change 8.7 [stmt.dcl] paragraph 5 as follows:</P></LI>

<BLOCKQUOTE>

<SPAN style="text-decoration:line-through;background-color:#FFA0A0">The destructor for a</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">A</SPAN> block-scope
object with static or thread storage duration will
be <SPAN style="text-decoration:line-through;background-color:#FFA0A0">executed</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">destroyed</SPAN> if and only if
it was constructed. [<I>Note:</I>
6.8.3.4 [basic.start.term] describes the
order in which block-scope objects with static and thread
storage duration are destroyed. &#8212;<I>end note</I>]

</BLOCKQUOTE>

<LI><P>Change 9.3 [dcl.init] paragraph 21 as follows:</P></LI>

<BLOCKQUOTE>

An object whose initialization has completed is deemed to be
constructed, even if <SPAN style="font-weight:bold;background-color:#A0FFA0">the object is of non-class type
or</SPAN> no constructor of the object's class is invoked for
the initialization. [<I>Note:</I> Such an object might have
been value-initialized or initialized by aggregate
initialization (9.3.1 [dcl.init.aggr]) or by an
inherited constructor
(10.9.3 [class.inhctor.init]). &#8212;<I>end note</I>]
<SPAN style="font-weight:bold;background-color:#A0FFA0">Destroying an object of class type invokes the destructor
of the class. Destroying a scalar type has no effect other than
ending the lifetime of the object (6.6.3 [basic.life]).
Destroying an array destroys each element in reverse subscript
order.</SPAN>

</BLOCKQUOTE>

<LI><P>Change 10.3.6 [class.dtor] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

<SPAN style="text-decoration:line-through;background-color:#FFA0A0">A destructor is used to destroy objects of its class
type.</SPAN> The address of a destructor...

</BLOCKQUOTE>

<LI><P>Change 13.2 [except.ctor] paragraphs 1 and 2 as
follows:</P></LI>

<BLOCKQUOTE>

<P>As control passes from the point where an exception is
thrown to a handler, <SPAN style="text-decoration:line-through;background-color:#FFA0A0">destructors are invoked</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">objects with automatic storage duration are
destroyed</SPAN> by a process, specified in this subclause,
called <I>stack unwinding</I>.</P>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">The destructor is invoked for each automatic object of class
type</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">Each object with automatic storage duration is
destroyed if it has been</SPAN> constructed, but not yet
destroyed, since the try block was entered. If an exception
is thrown during the destruction of temporaries or local
variables for a return statement
(8.6.3 [stmt.return]), the destructor for the
returned object (if any) is also invoked. The objects are
destroyed in the reverse order of the completion of their
construction. [<I>Example:</I>...</P>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2267"></A><H4>2267.
  
Copy-initialization of temporary in reference direct-initialization
</H4><B>Section: </B>9.3.3&#160; [dcl.init.ref]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2016-05-25




<P>Consider the following example:</P>

<PRE>
   struct A {} a; 
   struct B { explicit B(const A&amp;); }; 

   struct D { D(); }; 
   struct C { explicit operator D(); } c; 

   B b1(a);            //<SPAN style="font-family:Times;font-style:italic"> #1, ok </SPAN>
   const B &amp;b2{a};     //<SPAN style="font-family:Times;font-style:italic"> #2. ok </SPAN>
   const B &amp;b3(a);     //<SPAN style="font-family:Times;font-style:italic"> #3, error </SPAN>

   D d1(c);            //<SPAN style="font-family:Times;font-style:italic"> ok </SPAN>
   const D &amp;d2{c};     //<SPAN style="font-family:Times;font-style:italic"> ok </SPAN>
   const D &amp;d3(c);     //<SPAN style="font-family:Times;font-style:italic"> #6, ok </SPAN>
</PRE>

<P>The disparity between #3 and #6 is suprising, as is the difference from
#1 and #2. The reason for this difference is in 9.3.4 [dcl.init.list]
bullet 3.10:</P>

<BLOCKQUOTE>

Otherwise, if <TT>T</TT> is a reference type, a prvalue of the type
referenced by <TT>T</TT> is generated. The prvalue initializes its result
object by copy-list-initialization or direct-list-initialization, depending
on the kind of initialization for the reference. The prvalue is then used
to direct-initialize the reference.

</BLOCKQUOTE>

<P>(reflecting the resolution of issue 1494).</P>

<P><B>Notes from the March, 2018 meeting:</B></P>

<P>CWG felt that initialization of the temporary should always be copy
initialization, regardless of whether the top-level initialization is
copy or direct initialization. This would make #2, #3, #5, and #6 all
ill-formed.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<OL><LI><P>Change 9.3.4 [dcl.init.list] bullet 3.10 as follows:</P></LI>

<BLOCKQUOTE>

Otherwise, if <TT>T</TT> is a reference type, a prvalue of
the type referenced by <TT>T</TT> is generated. The prvalue
initializes its result object by
copy-list-initialization <SPAN style="text-decoration:line-through;background-color:#FFA0A0">or direct-list-initialization,
depending on the kind of initialization for the
reference</SPAN>. The prvalue is then used to
direct-initialize the reference. [Note: As usual, the
binding will fail and the program is ill-formed if the
reference type is an lvalue reference to a non-const type.
&#8212;end note]

</BLOCKQUOTE>

<LI><P>Add the following to the example in 9.3.4 [dcl.init.list]
bullet 3.10:</P></LI>

<PRE>
<SPAN style="font-weight:bold;background-color:#A0FFA0">  struct A { } a;
  struct B { explicit B(const A&amp;); };
  const B &amp;b2(a);  //<SPAN style="font-family:Times;font-style:italic"> error: cannot copy-initialize </SPAN>B<SPAN style="font-family:Times;font-style:italic"> temporary from </SPAN>A</SPAN>
</PRE>

<LI><P>Change 11.3.1.6 [over.match.ref] bullet 1.1 as follows:</P></LI>

<BLOCKQUOTE>

...For direct-initialization, those explicit conversion
functions that are not hidden within <TT>S</TT>
and yield type
&#8220;lvalue reference to <I>cv2</I>
<TT>T2</TT>&#8221; <SPAN style="font-weight:bold;background-color:#A0FFA0">(when initializing an lvalue reference or
an rvalue reference to function)</SPAN> <SPAN style="text-decoration:line-through;background-color:#FFA0A0"> or &#8220;<I>cv2</I>
<TT>T2</TT>&#8221;</SPAN>
or &#8220;rvalue reference to <I>cv2</I>
<TT>T2</TT>&#8221; <SPAN style="font-weight:bold;background-color:#A0FFA0">(when initializing an rvalue
reference or an lvalue reference to
function)</SPAN>, <SPAN style="text-decoration:line-through;background-color:#FFA0A0">respectively,</SPAN> where <TT>T2</TT>
is the same type as <TT>T</TT> or can be converted to
type <TT>T</TT> with a qualification conversion
(7.3.5 [conv.qual]), are also candidate functions.

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2278"></A><H4>2278.
  
Copy elision in constant expressions reconsidered
</H4><B>Section: </B>7.7&#160; [expr.const]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2016-06-27




<P>The resolution of issue 2022 does not work,
as it is mathematically impossible to guarantee the named return value
optimization in all cases. For example:</P>

<PRE>
  struct B { B *self = this; }; 
  extern const B b; 
  constexpr B f() { 
    B b; 
    if (&amp;b == &amp;::b) return B(); 
    else return b; 
  } 
  constexpr B b = f(); //<SPAN style="font-family:Times;font-style:italic"> is </SPAN>b.self == &amp;b<SPAN style="font-family:Times;font-style:italic">?</SPAN>
</PRE>

<P>Here an implementation is required to perform the optimization if
and only if it does not perform the optimization.</P>

<P>The resolution would appear to be to reverse the resolution of
issue 2022 and guarantee that named return
value optimization is <B>not</B> performed in constant expression
evaluation.</P>

<P><B>Notes from the March, 2018 meeting:</B></P>

<P>CWG concurred with the suggested direction.</P>

<P><B>Proposed resolution (November, 2018)</B></P>

<OL><LI><P>Change 7.7 [expr.const] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

Expressions that satisfy these requirements, assuming that copy
elision <SPAN style="font-weight:bold;background-color:#A0FFA0">(10.9.5 [class.copy.elision])</SPAN>
is <SPAN style="font-weight:bold;background-color:#A0FFA0">not</SPAN> performed, are called <I>constant
expressions</I>. [Note: Constant expressions can be evaluated
during translation. &#8212;end note]

</BLOCKQUOTE>

<LI><P>Change 9.1.5 [dcl.constexpr] paragraph 7 as follows:</P></LI>

<BLOCKQUOTE>

<P>A call to a constexpr function produces the same result as a call
to an equivalent non-constexpr function in all respects except
that</P>

<UL><LI><P>a call to a constexpr function can appear in a constant
expression (7.7 [expr.const]) and</P></LI>

<LI><P>copy elision is <SPAN style="text-decoration:line-through;background-color:#FFA0A0">mandatory</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">not
performed</SPAN> in a constant expression
(10.9.5 [class.copy.elision]).</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 10.9.5 [class.copy.elision] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

...Copy elision is <SPAN style="text-decoration:line-through;background-color:#FFA0A0">required</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">not permitted</SPAN>
where an expression is evaluated in a context requiring a
constant expression (7.7 [expr.const]) and in constant
initialization (6.8.3.2 [basic.start.static]). [Note: Copy
elision might <SPAN style="text-decoration:line-through;background-color:#FFA0A0">not</SPAN> be performed if the same expression
is evaluated in another context. &#8212;end note]

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2303"></A><H4>2303.
  
Partial ordering and recursive variadic inheritance
</H4><B>Section: </B>12.9.2.1&#160; [temp.deduct.call]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>John Spicer
 &#160;&#160;&#160;

 <B>Date: </B>2016-05-24


<P>The status of an example like the following is not clear:</P>

<PRE>
  template &lt;typename... T&gt;              struct A;
  template &lt;&gt;                           struct A&lt;&gt; {};
  template &lt;typename T, typename... Ts&gt; struct A&lt;T, Ts...&gt; : A&lt;Ts...&gt; {};
  struct B : A&lt;int&gt; {};

  template &lt;typename... T&gt;
  void f(const A&lt;T...&gt;&amp;);

  void g() {
    f(B{});
  } 
</PRE>

<P>This seems to be ambiguous in the current wording because
<TT>A&lt;&gt;</TT> and <TT>A&lt;int&gt;</TT> both succeed in deduction.
It would be reasonable to prefer the more derived specialization.
</P>

<P><B>Notes from the March, 2018 meeting:</B></P>

<P>The relevant specification is in 12.9.2.1 [temp.deduct.call] bullet
4.3 and paragraph 5, which specifies that if there is more than one
possible deduced <TT>A</TT>, deduction fails. The consensus was to add
wording similar to that of overload resolution preferring
&#8220;nearer&#8221; base classes.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<P>Change 12.9.2.1 [temp.deduct.call] bullet 4.3 as follows:</P>

<BLOCKQUOTE>

<P>In general, the deduction process attempts to find template
argument values that will make the deduced A identical to A
(after the type A is transformed as described above). However,
there are three cases that allow a difference:</P>

<UL><LI><P>...</P></LI>

<LI><P>If <TT>P</TT> is a class and <TT>P</TT> has the
form <I>simple-template-id</I>, then the transformed <TT>A</TT>
can be a derived class <SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>D</TT></SPAN> of the
deduced <TT>A</TT>. Likewise, if <TT>P</TT> is a pointer to a
class of the form <I>simple-template-id</I>, the
transformed <TT>A</TT> can be a pointer to a derived
class <SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>D</TT></SPAN> pointed to by the
deduced <TT>A</TT>. <SPAN style="font-weight:bold;background-color:#A0FFA0">However, if there is a class <TT>C</TT>
that is a (direct or indirect) base class of <TT>D</TT> and
derived (directly or indirectly) from a class <TT>B</TT> and that
would be a valid deduced <TT>A</TT>, the deduced <TT>A</TT>
cannot be <TT>B</TT> or pointer to <TT>B</TT>, respectively.
[<I>Example:</I></SPAN></P></LI>

<PRE>
<SPAN style="font-weight:bold;background-color:#A0FFA0">  template &lt;typename... T&gt; struct X;
  template &lt;&gt; struct X&lt;&gt; {};
  template &lt;typename T, typename... Ts&gt; struct X&lt;T, Ts...&gt; : X&lt;Ts...&gt; {};
  struct D : X&lt;int&gt; {};

  template &lt;typename... T&gt;
  int f(const X&lt;T...&gt;&amp;);
  int x = f(D());  //<SPAN style="font-family:Times;font-style:italic"> calls </SPAN>f&lt;int&gt;<SPAN style="font-family:Times;font-style:italic">, not </SPAN>f&lt;&gt;
                   //<SPAN style="font-family:Times;font-style:italic"> </SPAN>B<SPAN style="font-family:Times;font-style:italic"> is </SPAN>X&lt;&gt;<SPAN style="font-family:Times;font-style:italic">, </SPAN>C<SPAN style="font-family:Times;font-style:italic"> is </SPAN>X&lt;int&gt;</SPAN>
</PRE>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">&#8212;<I>end example</I>]</SPAN></P>

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2309"></A><H4>2309.
  
Restrictions on nested statements within <TT>constexpr</TT> functions
</H4><B>Section: </B>9.1.5&#160; [dcl.constexpr]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Faisal Vali
 &#160;&#160;&#160;

 <B>Date: </B>2016-07-30




<P>Section 9.1.5 [dcl.constexpr] bullet 3.4 specifies a list of
constructs that that the body of a <TT>constexpr</TT> function shall
not contain. However, the meaning of the word &#8220;contain&#8221; is
not clear. For example, are things appearing in the body of a nested
<TT>constexpr</TT> lambda &#8220;contained&#8221; in the body of the
<TT>constexpr</TT> function?
</P>



<P><B>Proposed resolution (November, 2018):</B></P>

<OL><LI><P>Add the following two paragraphs after
8 [stmt.stmt] paragraph 1:</P></LI>

<BLOCKQUOTE>

<P>...The optional <I>attribute-specifier-seq</I> appertains to the
respective statement.</P>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">A <I>substatement</I> of a <I>statement</I> is one of the
following:</SPAN></P>

<UL><LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">for a <I>labeled-statement</I>, its
contained <I>statement</I>,</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">for a <I>compound-statement</I>, any <I>statement</I> of
its <I>statement-seq</I>,</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">for a <I>selection-statement</I>, any of its <I>statement</I>s
(but not its <I>init-statement</I>), or</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">for an <I>iteration-statement</I>, its contained
<I>statement</I> (but not an <I>init-statement</I>).</SPAN></P></LI>

</UL>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">[<I>Note:</I> The <I>compound-statement</I> of
a <I>lambda-expression</I> is not a substatement of
the <I>statement</I> (if any) in which the <I>lambda-expression</I>
lexically appears. &#8212;<I>end note</I>]</SPAN></P>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">A <I>statement</I> <TT>S1</TT> <I>encloses</I> a
<I>statement</I> <TT>S2</TT> if</SPAN></P>

<UL><LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>S2</TT> is a substatement of <TT>S1</TT>
(9 [dcl.dcl]),</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>S1</TT> is a <I>selection-statement</I> or
<I>iteration-statement</I> and <TT>S2</TT> is the
<I>init-statement</I> of <TT>S1</TT>,</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>S1</TT> is a <I>try-block</I> and <TT>S2</TT>
is its <I>compound-statement</I> or any of the
<I>compound-statement</I>s of its <I>handler</I>s, or</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>S1</TT> encloses a statement <TT>S3</TT> and
<TT>S3</TT> encloses <TT>S2</TT>.</SPAN></P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Delete the following sentence from 8.4 [stmt.select]
paragraph 1:</P></LI>

<BLOCKQUOTE>

<SPAN style="text-decoration:line-through;background-color:#FFA0A0">In 8 [stmt.stmt], the term substatement refers to
the contained statement or statements that appear in the syntax
notation.</SPAN>

</BLOCKQUOTE>

<LI><P>Change 9.1.5 [dcl.constexpr] bullet 3.3 as follows:</P></LI>

<BLOCKQUOTE>

<P>The definition of a constexpr function shall satisfy the
following requirements:</P>

<UL><LI><P>...</P></LI>

<LI>

<P>its <I>function-body</I> shall be <TT>= delete</TT>, <TT>=
default</TT>, or a <I>compound-statement</I> that does not
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">contain</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">enclose (8 [stmt.stmt]
</SPAN></P></LI>

<UL><LI><P>...</P></LI>

</UL>

</UL>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2310"></A><H4>2310.
  
Type completeness and derived-to-base pointer conversions
</H4><B>Section: </B>7.3.11&#160; [conv.ptr]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2016-08-08




<P>The specification of derived-to-base pointer conversions in
7.3.11 [conv.ptr] paragraph 3 does not require that the derived
class be complete at the point of the conversion. This leaves unclear the
status of an example like the following, on which there is implementation
divergence:</P>

<PRE>
  template&lt;typename A, typename B&gt; struct check_derived_from { 
    static A a; 
    static constexpr B *p = &amp;a; 
  }; 
  struct W {}; 
  struct X {}; 
  struct Y {}; 
  struct Z : W, 
    X, check_derived_from&lt;Z, X&gt;,  //<SPAN style="font-family:Times;font-style:italic"> #1 </SPAN>
    check_derived_from&lt;Z, Y&gt;, Y { //<SPAN style="font-family:Times;font-style:italic"> #2 </SPAN>
    check_derived_from&lt;Z, W&gt; cdf; //<SPAN style="font-family:Times;font-style:italic"> #3 </SPAN>
  }; 
</PRE>

<P><B>Notes from the March, 2018 meeting:</B></P>

<P>The consensus of CWG was that the derived class must be complete at
the point of the conversion, and thus all three attempted conversions in
the example are ill-formed.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<OL><LI><P>Change 7.3.11 [conv.ptr] paragraph 3 as follows:</P></LI>

<BLOCKQUOTE>

A prvalue of type &#8220;pointer to <I>cv</I>
<TT>D</TT>&#8221;, where <TT>D</TT> is a <SPAN style="font-weight:bold;background-color:#A0FFA0">complete</SPAN>
class type, can be converted to a prvalue of type
&#8220;pointer to <I>cv</I>
<TT>B</TT>&#8221;, where <TT>B</TT> is a base class
(10.6 [class.derived]) of <TT>D</TT>. If <TT>B</TT> is
an inaccessible...

</BLOCKQUOTE>

<LI><P>Change 7.3.12 [conv.mem] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

A prvalue of type &#8220;pointer to member of <TT>B</TT> of
type <I>cv</I> <TT>T</TT>&#8221;, where B<TT></TT> is a
class type, can be converted to a prvalue of type
&#8220;pointer to member of <TT>D</TT> of type <I>cv</I>
<TT>T</TT>&#8221;, where <TT>D</TT>
is a <SPAN style="font-weight:bold;background-color:#A0FFA0">complete class</SPAN>
derived <SPAN style="text-decoration:line-through;background-color:#FFA0A0">class</SPAN>
(10.6 [class.derived]) <SPAN style="text-decoration:line-through;background-color:#FFA0A0">of</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">from</SPAN>
<TT>B</TT>. If <TT>B</TT>
is an inaccessible...

</BLOCKQUOTE>

<LI><P>Change 7.6.1.9 [expr.static.cast] paragraphs 11 and 12 as
followed:</P></LI>

<BLOCKQUOTE>

<P>A prvalue of type &#8220;pointer to <I>cv1</I>
<TT>B</TT>&#8221;, where <TT>B</TT>
is a <SPAN style="font-weight:bold;background-color:#A0FFA0">complete</SPAN>
class type, can be converted to a prvalue of type
&#8220;pointer to <I>cv2</I>
<TT>D</TT>&#8221;, where D is a class derived
(10.6 [class.derived]) from B , if cv2 is the same...</P>

<P>A prvalue of type &#8220;pointer to member of <TT>D</TT>
of type <I>cv1</I>
<TT>T</TT>&#8221; can be converted to a prvalue of type
&#8220;pointer to member of <TT>B</TT>
of type <I>cv2</I>
<TT>T</TT>&#8221;, where <TT>B</TT>
is a base class (10.6 [class.derived]) of <SPAN style="font-weight:bold;background-color:#A0FFA0">a complete class</SPAN>
<TT>D</TT>, if <I>cv2</I>
is the same...</P>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2317"></A><H4>2317.
  
Self-referential default member initializers
</H4><B>Section: </B>10.9.2&#160; [class.base.init]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2016-08-29




<P>Consider an example like:</P>

<PRE>
  struct A { 
    int n = A{}.n; 
  }; 
</PRE>

<P>There doesn't seem to be a good reason to support this kind of thing,
and it would be simpler to say that a default member initializer can't
trigger any direct or indirect use of itself in general, rather than just
the two special cases that were banned by issues 1696 and 1397.</P>

<P><B>Notes from the March, 2018 meeting:</B></P>

<P>There was a suggestion that creating an object of the containing
class in a default member initializer should be prohibited. That would
presumably be a difference between the reference member and non-reference
member cases, since the intent is to allow creation of a temporary for
a reference member to bind to. The suggested approach for drafting was
simply to remove the restriction to references in 9.3.1 [dcl.init.aggr]
paragraph 11.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<P>Change 9.3.1 [dcl.init.aggr] paragraph 12 as follows:</P>

<BLOCKQUOTE>

If a <SPAN style="text-decoration:line-through;background-color:#FFA0A0">reference</SPAN> member <SPAN style="text-decoration:line-through;background-color:#FFA0A0">is initialized from
its</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">has a</SPAN> default member initializer and a
potentially-evaluated subexpression thereof is an aggregate
initialization that would use that default member
initializer, the program is ill-formed.  [<I>Example:</I>

<PRE>
  struct A;
  extern A a;
  struct A {
    const A&amp; a1 { A{a,a} }; //<SPAN style="font-family:Times;font-style:italic"> OK</SPAN>
    const A&amp; a2 { A{} };    //<SPAN style="font-family:Times;font-style:italic"> error</SPAN>
  };
  A a{a,a};                 //<SPAN style="font-family:Times;font-style:italic"> OK</SPAN>

<SPAN style="font-weight:bold;background-color:#A0FFA0">  struct B {
  int n = B{}.n;            //<SPAN style="font-family:Times;font-style:italic"> error</SPAN>
  };</SPAN>
</PRE>

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

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2318"></A><H4>2318.
  
Nondeduced contexts in deduction from a <I>braced-init-list</I>
</H4><B>Section: </B>12.9.2.5&#160; [temp.deduct.type]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Jonathan Caves
 &#160;&#160;&#160;

 <B>Date: </B>2016-08-12


<P>The status of an example like the following is unclear:</P>

<PRE>
  template&lt;typename T, int N&gt; void g(T (* const (&amp;)[N])(T)) { }

  int f1(int);
  int f4(int);
  char f4(char);

  void f() {
    g({ &amp;f1, &amp;f4 });  //<SPAN style="font-family:Times;font-style:italic"> OK, </SPAN>T<SPAN style="font-family:Times;font-style:italic"> deduced to </SPAN>int<SPAN style="font-family:Times;font-style:italic">, </SPAN>N<SPAN style="font-family:Times;font-style:italic"> deduced to </SPAN>2<SPAN style="font-family:Times;font-style:italic">?</SPAN>
  }
</PRE>

<P>The problem is the interpretation of 12.9.2.5 [temp.deduct.type]
paragraph 4:</P>

<BLOCKQUOTE>

In most cases, the types, templates, and non-type values that are used to
compose <TT>P</TT> participate in template argument deduction. That is,
they may be used to determine the value of a template argument, and the
value so determined must be consistent with the values determined
elsewhere. In certain contexts, however, the value does not participate in
type deduction, but instead uses the values of template arguments that were
either deduced elsewhere or explicitly specified. If a template parameter
is used only in non-deduced contexts and is not explicitly specified,
template argument deduction fails.

</BLOCKQUOTE>

<P>According to 12.9.2.1 [temp.deduct.call] paragraph 1, deduction is
performed independently for each element of the initializer list:</P>

<BLOCKQUOTE>

Template argument deduction is done by comparing each function template
parameter type (call it <TT>P</TT>) that
contains <I>template-parameter</I>s that participate in template argument
deduction with the type of the corresponding argument of the call (call it
<TT>A</TT>) as described below. If removing references and cv-qualifiers
from <TT>P</TT> gives <TT>std::initializer_list&lt;P'&gt;</TT>
or <TT>P'[[N]</TT> for some <TT>P'</TT> and <TT>N</TT> and the argument is a
non-empty initializer list (9.3.4 [dcl.init.list]), then deduction is
performed instead for each element of the initializer list,
taking <TT>P'</TT> as a function template parameter type and the
initializer element as its argument, and in the <TT>P'[N]</TT> case,
if <TT>N</TT> is a non-type template parameter, <TT>N</TT> is deduced from
the length of the initializer list. Otherwise, an initializer list argument
causes the parameter to be considered a non-deduced context
(12.9.2.5 [temp.deduct.type]).

</BLOCKQUOTE>

<P>Deduction fails for the second element of the list, <TT>&amp;f4</TT>,
because of ambiguity. Does this mean that deduction fails for the entire
call, or does the successful deduction of <TT>T</TT> from the first
element and <TT>N</TT> from the length of the list result in successful
deduction for the call?
</P>

<P><B>Notes from the July, 2017 meeting:</B></P>

<P>CWG determined that the call is well-formed.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<P>Change 12.9.2.1 [temp.deduct.call] paragraph 1 as follows:</P>

<BLOCKQUOTE>

<P>Template argument deduction is done by comparing each
function template parameter type (call it <TT>P</TT>) that
contains <I>template-parameter</I>s that participate in
template argument deduction with the type of the
corresponding argument of the call (call it <TT>A</TT>) as
described below. If removing references and cv-qualifiers
from <TT>P</TT>
gives <TT>std::initializer_list&lt;<TT>P'</TT>&gt;</TT>
or <TT>P' [N] </TT>for some <TT>P"</TT> and <TT>N</TT> and
the argument is a non-empty initializer list
(9.3.4 [dcl.init.list]), then deduction is performed
instead for each element of the initializer
list <SPAN style="font-weight:bold;background-color:#A0FFA0">independently</SPAN>, taking <TT>P'</TT> as
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">a</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">separate</SPAN> function template parameter
type<SPAN style="font-weight:bold;background-color:#A0FFA0">s <TT>P'</TT><SUB><I>i</I></SUB></SPAN>
and the <SPAN style="font-weight:bold;background-color:#A0FFA0"><I>i</I>-th</SPAN>
initializer element as <SPAN style="text-decoration:line-through;background-color:#FFA0A0">its</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">the corresponding</SPAN>
argument<SPAN style="font-weight:bold;background-color:#A0FFA0">.</SPAN>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, and in</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">In</SPAN> the <TT>P' [N]</TT> case,
if <TT>N</TT> is a non-type template parameter, <TT>N</TT>
is deduced from the length of the initializer
list. Otherwise, an initializer list argument causes the
parameter to be considered a non-deduced context
(12.9.2.5 [temp.deduct.type]). [<I>Example:</I></P>

<PRE>
  ...
  template&lt;class T, int N&gt; void n(T const(&amp;)[N], T);
  n({{1},{2},{3}},Aggr()); //<SPAN style="font-family:Times;font-style:italic"> OK, </SPAN>T<SPAN style="font-family:Times;font-style:italic"> is </SPAN>Aggr<SPAN style="font-family:Times;font-style:italic">, </SPAN>N<SPAN style="font-family:Times;font-style:italic"> is </SPAN>3

<SPAN style="font-weight:bold;background-color:#A0FFA0">  template&lt;typename T, int N&gt; void o(T (* const (&amp;)[N])(T)) { }
  int f1(int);
  int f4(int);
  char f4(char);
  o({ &amp;f1, &amp;f4 }); //<SPAN style="font-family:Times;font-style:italic"> OK, </SPAN>T<SPAN style="font-family:Times;font-style:italic"> deduced as </SPAN>int<SPAN style="font-family:Times;font-style:italic"> from first element, nothing deduced from second element, </SPAN>N<SPAN style="font-family:Times;font-style:italic"> deduced as </SPAN>2
  o({ &amp;f1, static_cast&lt;char(*)(char)&gt;(&amp;f4) }); //<SPAN style="font-family:Times;font-style:italic"> error: conflicting deductions for </SPAN>T</SPAN>
</PRE>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2330"></A><H4>2330.
  
Missing references to variable templates
</H4><B>Section: </B>12.8&#160; [temp.spec]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Daveed Vandevoorde
 &#160;&#160;&#160;

 <B>Date: </B>2016-12-06


<P>Presumably paragraphs 1-3 of 12.8 [temp.spec] are
intended to apply to variable templates, but the term does not
appear in the current wording of these paragraphs.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<OL><LI><P>Change 12.8 [temp.spec] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

The act of instantiating a function, <SPAN style="font-weight:bold;background-color:#A0FFA0">a variable,</SPAN>
a class, a member of a class template or a member template
is referred to as template instantiation.

</BLOCKQUOTE>

<LI><P>Change 12.8 [temp.spec] paragraphs 3 and r as
follows:</P></LI>

<BLOCKQUOTE>

<P>An explicit specialization may be declared for a function
template, <SPAN style="font-weight:bold;background-color:#A0FFA0">a variable template,</SPAN> a class template,
a member of a class template or a member template. An
explicit specialization declaration is introduced by
template&lt;&gt; . In an explicit specialization declaration
for <SPAN style="font-weight:bold;background-color:#A0FFA0">a variable template,</SPAN> a class template, a
member of a class template or a class member template, the
name of the <SPAN style="font-weight:bold;background-color:#A0FFA0">the variable or</SPAN> class that is
explicitly specialized shall be
a <I>simple-template-id</I>. In the explicit specialization
declaration for a function template or a member function
template, the name of the function or member function
explicitly specialized may be
a <I>template-id</I>. [<I>Example:</I>...</P>

<P>An instantiated template specialization can be either
implicitly instantiated (12.8.1 [temp.inst]) for a
given argument list or be explicitly instantiated
(12.8.2 [temp.explicit]). A specialization is a class,
<SPAN style="font-weight:bold;background-color:#A0FFA0">variable,</SPAN> function, or class member that is
either instantiated or explicitly specialized
(12.8.3 [temp.expl.spec]).</P>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2331"></A><H4>2331.
  
Redundancy in description of class scope
</H4><B>Section: </B>6.3.7&#160; [basic.scope.class]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Thomas K&#246;ppe
 &#160;&#160;&#160;

 <B>Date: </B>2016-12-07


<P>The first four paragraphs of 6.3.7 [basic.scope.class] are
somewhat redundant. In particular:</P>

<UL><LI><P>The normative paragraphs are 4 and 2.</P></LI>

<LI><P>Paragraph 1 is subsumed by paragraph 4.</P></LI>

<LI><P>Paragraph 3 follows from existing rules for name hiding.</P></LI>

</UL>

<P>This
is <A HREF="https://github.com/cplusplus/draft/issues/1169">editorial
issue 1169</A>.
</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<P>In 6.3.7 [basic.scope.class], delete paragraph 1, move paragraph 4 to
the beginning, and make paragraph 3 a note:</P>

<BLOCKQUOTE>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">The potential scope of a name declared in a class consists
not only of the declarative region following the name's
point of declaration, but also of all complete-class
contexts (10.3 [class.mem]) of that class.</SPAN>
</P>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">The potential scope of a declaration that extends to or past
the end of a class definition also extends to the regions
defined by its member definitions, even if the members are
defined lexically outside the class (this
includes static data member definitions, nested class
definitions, and member function definitions, including the
member function body and any portion of the declarator part
of such definitions which follows the <I>declarator-id</I>,
including a <I>parameter-declaration-clause</I> and any
default arguments (9.2.3.6 [dcl.fct.default])).</SPAN></P>

<P>A name <TT>N</TT> used in a class <TT>S</TT> shall refer
to the same declaration in its context and when re-evaluated
in the completed scope of <TT>S</TT>. No diagnostic is
required for a violation of this rule.</P>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">[<I>Note:</I></SPAN>
A name declared within a member function hides a declaration
of the same name whose scope extends to or past the end of
the member function's class <SPAN style="font-weight:bold;background-color:#A0FFA0">(6.3.10 [basic.scope.hiding])</SPAN>.
<SPAN style="font-weight:bold;background-color:#A0FFA0">&#8212;<I>end note</I>]</SPAN></P>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">The potential scope of a declaration that extends to or past
the end of a class definition also extends to the regions
defined by its member definitions, even if the members are
defined lexically outside the class (this
includes static data member definitions, nested class
definitions, and member function definitions, including the
member function body and any portion of the declarator part
of such definitions which follows the <I>declarator-id</I>,
including a <I>parameter-declaration-clause</I> and any
default arguments (9.2.3.6 [dcl.fct.default])).</SPAN></P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2332"></A><H4>2332.
  
<I>template-name</I> as <I>simple-type-name</I> vs injected-class-name
</H4><B>Section: </B>9.1.7.2&#160; [dcl.type.simple]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Daveed Vandevoorde
 &#160;&#160;&#160;

 <B>Date: </B>2016-12-10


<P>Paper <A HREF="http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0091r3.html">P0091R3</A>
has the following example:</P>

<PRE>
  template&lt;typename T&gt; struct X {
    template&lt;typename Iter&gt;
    X(Iter b, Iter e) { /* ... */ }

    template&lt;typename Iter&gt;
    auto foo(Iter b, Iter e) { 
      return X(b, e); //<SPAN style="font-family:Times;font-style:italic"> </SPAN>X&lt;U&gt;<SPAN style="font-family:Times;font-style:italic"> to avoid breaking change</SPAN>
    }

    template&lt;typename Iter&gt;
    auto bar(Iter b, Iter e) { 
      return X&lt;Iter::value_type&gt;(b, e); //<SPAN style="font-family:Times;font-style:italic"> Must specify what we want</SPAN>
    }
  };
</PRE>

<P>The intent was presumably to avoid breaking existing code,
but the new wording in 9.1.7.2 [dcl.type.simple] paragraph 2
appears to make the expression <TT>X(b, e)</TT> ill-formed:</P>

<BLOCKQUOTE>

A <I>type-specifier</I> of the form
<TT>typename</TT><I><SUB>opt</SUB></I>
<I>nested-name-specifier<SUB>opt</SUB> template-name</I> is a
placeholder for a deduced class type
(9.1.7.5 [dcl.type.class.deduct]). The <I>template-name</I> shall
name a class template that is not an injected-class-name.

</BLOCKQUOTE>

<P><U>Suggested resolution:</U></P>

<P>Deleting the wording in question and replacing it with a
cross-reference to 12.7.1 [temp.local], which makes it
clear that the injected-class-name is a <I>type-name</I> and
not a <I>template-name</I> in this context, would seem to address
the problem adequately.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<P>Change 9.1.7.2 [dcl.type.simple] paragraph 2 as follows:</P>

<BLOCKQUOTE>

The <I>simple-type-specifier</I> <TT>auto</TT>
is a placeholder for a
type to be deduced
(9.1.7.4 [dcl.spec.auto]). A <I>type-specifier</I> of
the form <TT>typename</TT><SUB><I>opt</I></SUB>
<I>nested-name-specifier<SUB>opt</SUB> template-name</I> is a placeholder for a
deduced class type
(9.1.7.5 [dcl.type.class.deduct]). The <I>template-name</I>
shall name a class template <SPAN style="text-decoration:line-through;background-color:#FFA0A0">that is not
an <I>injected-class-name</I></SPAN>. <SPAN style="font-weight:bold;background-color:#A0FFA0">[<I>Note:</I> An
injected-class-name is never interpreted as
a <I>template-name</I> in contexts where
a <I>type-specifier</I> may appear
(12.7.1 [temp.local]). &#8212;<I>end note</I>]</SPAN>
The other <I>simple-type-specifier</I>s specify...

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2336"></A><H4>2336.
  
Destructor characteristics vs potentially-constructed subobjects
</H4><B>Section: </B>13.4&#160; [except.spec]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Nathan Sidwell
 &#160;&#160;&#160;

 <B>Date: </B>2017-02-28


<P>According to 13.4 [except.spec] paragraph 8,</P>

<BLOCKQUOTE>

The exception specification for an implicitly-declared
destructor, or a destructor without a <I>noexcept-specifier</I>,
is potentially-throwing if and only if any of the destructors for
any of its potentially constructed subojects is potentially
throwing.

</BLOCKQUOTE>

<P>10.3.3 [special] paragraph 5 defines &#8220;potentially
constructed subobjects&#8221; as follows:</P>

<BLOCKQUOTE>

For a class, its non-static data members, its non-virtual direct
base classes, and, if the class is not abstract
(10.6.3 [class.abstract]), its virtual base classes are called
its potentially constructed subobjects.

</BLOCKQUOTE>

<P>This leads to the following problem:</P>

<PRE>
  class V {
  public:
    virtual ~V() noexcept(false);
  };

  class B : virtual V {
    virtual void foo () = 0;
    //<SPAN style="font-family:Times;font-style:italic"> implicitly defined </SPAN>virtual ~B () noexcept(true);
  };

  class D : B {
    virtual void foo ();
    //<SPAN style="font-family:Times;font-style:italic"> implicitly defined </SPAN>virtual ~D () noexcept(false);
  };
</PRE>

<P>Here, <TT>D::~D()</TT> is throwing but overrides the non-throwing
<TT>B::~B()</TT>.</P>

<P>There are similar problems with the deletedness of
destructors per 10.3.6 [class.dtor] paragraph 5, which
also only considers potentially constructed subobjects.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<P>Change 13.4 [except.spec] paragraph 8 as follows:</P>

<BLOCKQUOTE>

The exception specification for an implicitly-declared
destructor, or a destructor without
a <I>noexcept-specifier</I>, is potentially-throwing if and
only if any of the destructors for any of its potentially
constructed subobjects is <SPAN style="text-decoration:line-through;background-color:#FFA0A0">potentially throwing</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">potentially-throwing or the destructor is virtual and
the destructor of any virtual base class is
potentially-throwing</SPAN>.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2352"></A><H4>2352.
  
Similar types and reference binding
</H4><B>Section: </B>9.3.3&#160; [dcl.init.ref]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Richard Smith
 &#160;&#160;&#160;

 <B>Date: </B>2017-07-14


<P>In an example like</P>

<PRE>
  int *ptr;
  const int *const &amp;f() {
    return ptr;
  }
</PRE>

<P>What is returned is a reference to a temporary instead of binding
directly to <TT>ptr</TT>. The rules for reference-related types should
say that <TT>T</TT> is reference-related to <TT>U</TT> if <TT>U*</TT>
can be converted to <TT>T*</TT> by a qualification conversion.</P>

<P><B>Notes from the April, 2018 teleconference:</B></P>

<P>CWG agreed with the proposed direction.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<P>Change 9.3.3 [dcl.init.ref] paragraph 4 as follows:</P>

<BLOCKQUOTE>

<P>Given types &#8220;<I>cv1</I>
<TT>T1</TT>&#8221; and &#8220;<I>cv2</I>
<TT>T2</TT>&#8221;,
&#8220;<I>cv1</I>
<TT>T1</TT>&#8221; is <I>reference-related</I>
to &#8220;<I>cv2</I>
<TT>T2</TT>&#8221; if <TT>T1</TT>
is <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the same type as</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">similar (7.3.5 [conv.qual]) to</SPAN>
<TT>T2</TT>, or <TT>T1</TT>
is a base class
of <TT>T2</TT>. &#8220;<I>cv1</I>
<TT>T1</TT>&#8221; is <I>reference-compatible</I>
with
&#8220;<I>cv2</I>
<TT>T2</TT>&#8221; if</P>

<UL><LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>T1</TT> is reference-related to <TT>T2</TT>, or</SPAN>
</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>T2</TT>
is &#8220;<TT>noexcept</TT>
function&#8221; and <TT>T1</TT>
is
&#8220;function&#8221;, where the function types are
otherwise the same,</SPAN>
</P></LI>

</UL>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">and <I>cv1</I> is the same cv-qualification as, or
greater cv-qualification than, <I>cv2</I></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">a prvalue of type &#8220;pointer to <I>cv2</I>
<TT>T2</TT>&#8221; can be converted to the type
&#8220;pointer to <I>cv1</I> <TT>T1</TT>&#8221; via a
standard conversion sequence
(7.3 [conv])</SPAN>. In all cases where the
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">reference-related or</SPAN>
reference-compatible relationship of
two types is used to establish the validity of a reference
binding<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, and <TT>T1</TT> is a base class of <TT>T2</TT></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">and the standard conversion sequence would be
ill-formed</SPAN>, a program that necessitates such a binding
is ill-formed <SPAN style="text-decoration:line-through;background-color:#FFA0A0">if <TT>T1</TT> is an inaccessible
(10.8 [class.access]) or ambiguous
(10.7 [class.member.lookup]) base class of <TT>T2</TT></SPAN>.</P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2358"></A><H4>2358.
  
Explicit capture of value
</H4><B>Section: </B>7.5.5.2&#160; [expr.prim.lambda.capture]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Daveed Vandevoorde
 &#160;&#160;&#160;

 <B>Date: </B>2017-09-20


<P>The status of an example like the following is unclear:</P>

<PRE>
  int foo(int a = ([loc=1] { return loc; })()) { return a; }
</PRE>

<P>because of 7.5.5.2 [expr.prim.lambda.capture] paragraph 9:</P>

<BLOCKQUOTE>

A <I>lambda-expression</I> appearing in a default argument shall not
implicitly or explicitly capture any entity.

</BLOCKQUOTE>

<P>However, there doesn't appear to be a good reason for prohibiting
such a capture.</P>

<P><B>Notes from the April, 2018 teleconference:</B></P>

<P>CWG felt that the rule for capturing should be something like the
prohibition for local classes odr-using a variable with automatic storage
duration in 10.5 [class.local] paragraph 1.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<P>Change 7.5.5.2 [expr.prim.lambda.capture] paragraph 9 as follows:</P>

<BLOCKQUOTE>

<P>A <I>lambda-expression</I> appearing in a default
argument shall not implicitly or explicitly capture any
entity<SPAN style="font-weight:bold;background-color:#A0FFA0">, except for an <I>init-capture</I> for which any
full-expression in its <I>initializer</I> satisfies the
constraints of an expression appearing in a default argument
(9.2.3.6 [dcl.fct.default])</SPAN>.
[<I>Example:</I></P>

<PRE>
  void f2() {
    int i = 1;
    void g1(int = ([i]{ return i; })());       //<SPAN style="font-family:Times;font-style:italic"> ill-formed</SPAN>
    void g2(int = ([i]{ return 0; })());       //<SPAN style="font-family:Times;font-style:italic"> ill-formed</SPAN>
    void g3(int = ([=]{ return i; })());       //<SPAN style="font-family:Times;font-style:italic"> ill-formed</SPAN>
    void g4(int = ([=]{ return 0; })());       //<SPAN style="font-family:Times;font-style:italic"> OK</SPAN>
    void g5(int = ([]{ return sizeof i; })()); //<SPAN style="font-family:Times;font-style:italic"> OK</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">    void g6(int = ([x=1] { return x; })();     //<SPAN style="font-family:Times;font-style:italic"> OK</SPAN>
    void g7(int = ([x=i] { return x; })();     //<SPAN style="font-family:Times;font-style:italic"> ill-formed</SPAN></SPAN>
  }
</PRE>

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

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2360"></A><H4>2360.
  
<TT>[[maybe_unused]]</TT> and structured bindings
</H4><B>Section: </B>9.11.8&#160; [dcl.attr.unused]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Michael Wong
 &#160;&#160;&#160;

 <B>Date: </B>2017-10-19


<P>According to9.11.8 [dcl.attr.unused] paragraph 2,</P>

<BLOCKQUOTE>

The attribute may be applied to the declaration of a class,
a <I>typedef-name</I>, a variable, a non-static data member, a function, an
enumeration, or an enumerator.

</BLOCKQUOTE>

<P>This does not include structured bindings, although there seems to be
no good reason to prohibit uses like</P>

<PRE>
  [[maybe_unused]] auto [a, b] = std::make_pair(42, 0.23);
</PRE>

<P><B>Notes from the October, 2018 teleconference:</B></P>

<P>CWG agreed that such an annotation should be permitted and apply
to the underlying variable; i.e., a compiler might warn in the absence
of such an attribute if none of the structured bindings were used, and
the presence of the attribute would silence such warnings.</P>

<P><B>Proposed resolution (November, 2018):</B></P>

<P>Change 9.11.8 [dcl.attr.unused] paragraphs 2 and 3 as
follows:</P>

<BLOCKQUOTE>

<P>The attribute may be applied to the declaration of a class,
a <I>typedef-name</I>, a variable <SPAN style="font-weight:bold;background-color:#A0FFA0">(including a structured
binding declaration)</SPAN>, a non-static data member,
a function, an enumeration, or an enumerator.</P>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">[<I>Note:</I></SPAN> For an entity
marked <TT>maybe_unused</TT>, implementations should not
emit a warning that the entity <SPAN style="text-decoration:line-through;background-color:#FFA0A0">is</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">or its structured bindings
(if any) are used or</SPAN>
unused<SPAN style="font-weight:bold;background-color:#A0FFA0">.</SPAN>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, or that the entity
is used despite the presence of the attribute. &#8212;<I>end
note</I>]</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">For a structured binding declaration
not marked <TT>maybe_unused</TT>, implementations should not
emit such a warning unless all of its structured bindings are
unused.</SPAN></P>

</BLOCKQUOTE>

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