<HTML>
<HEAD>
<META http-equiv="Content-Type" content="text/html; charset=us-ascii">
<TITLE>
    Core "tentatively ready" Issues
   </TITLE>
</HEAD>
<BODY>
<TABLE ALIGN="RIGHT" CELLSPACING="0" CELLPADDING="0">
<TR>
<TD ALIGN="RIGHT">
      Document number:
     </TD>
<TD>
       &#160;P1968R0</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Date:
     </TD>
<TD>
      &#160;2019-11-07</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 "tentatively ready" Issues
     for the
     November, 2019 (Belfast) 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/2019/n4835.pdf">WG21 N4835</A>.
   </P>
<HR><A NAME="1621"></A><H4>1621.
  
Member initializers in anonymous unions
</H4><B>Section: </B>11.10.2&#160; [class.base.init]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2013-02-12


<P>The effect of a non-static data member initializer in an anonymous
union is not clearly described in the current wording.  Consider the
following example:</P>

<PRE>
  struct A {
    struct B {
      union {
        int x = 37;
      };
      union {
        int y = x + 47;  //<SPAN style="font-family:Times;font-style:italic"> Well-formed?</SPAN>
      };
    } a;
  }; 
</PRE>

<P>Does an anonymous union have a constructor that applies a non-static
data member initializer?  Or is the initialization performed by the
constructor of the class in which the anonymous union appears?  In
particular, is the reference to <TT>x</TT> in the initializer for
<TT>y</TT> well-formed or not?  If the initialization of <TT>y</TT>
is performed by <TT>B</TT>'s constructor, there is no problem because
<TT>B::x</TT> is a member of the object being initialized.  If an anonymous
union has its own constructor, <TT>B::x</TT> is just a member of the
containing class and is a reference to a non-static data member without an
object, which is ill-formed.  Implementations currently appear to take the
latter interpretation and report an error for that initializer.</P>



<P>As a further example, consider:</P>

<PRE>
  union {       //<SPAN style="font-family:Times;font-style:italic"> #1</SPAN>
    union {     //<SPAN style="font-family:Times;font-style:italic"> #2</SPAN>
      union {   //<SPAN style="font-family:Times;font-style:italic"> #3</SPAN>
        int y = 32;
      };
    };
  } a { } ;
</PRE>

<P>One interpretation might be that union #3 has a non-trivial default
constructor because of the initializer of <TT>y</TT>, which would give
union #2 a deleted default constructor, which would make the example
ill-formed.</P>

<P>As yet another example, consider:</P>

<PRE>
  union {
    union {
      int x;
    };
    union {
      int y = 3;
    };
    union {
      int z;
    };
  } a { };
</PRE>

<P>Assuming the current proposed resolution of issue 1502, what is the correct interpretation of this code?  Is it
well-formed, and if so, what initialization is performed?</P>

<P>Finally, consider</P>

<PRE>
  struct S {
    union { int x = 1; };
    union { int y = 2; };
  } s{};
</PRE>

<P>Does this violate the prohibition of aggregates containing
member initializers in 9.4.1 [dcl.init.aggr] paragraph 1?</P>

<P>See also issues 1460,
1562, 1587,
and 1623.</P>



<P><B>Proposed resolution (October, 2019):</B></P>

<OL><LI><P>Change 11.4.2 [class.mfct.non-static] paragraph 1 as
follows:</P></LI>

<BLOCKQUOTE>

...A non-static member function may also be called directly
using the function call syntax
(7.6.1.2 [expr.call],
12.4.1.1 [over.match.call]) from within <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the body of a
member function of</SPAN>
its class or <SPAN style="text-decoration:line-through;background-color:#FFA0A0">of</SPAN>
a class derived from its
class<SPAN style="font-weight:bold;background-color:#A0FFA0">, or a member thereof, as described below.</SPAN>
.
</BLOCKQUOTE>

<LI><P>Change 11.4.2 [class.mfct.non-static] paragraph 3 as follows:</P></LI>

<BLOCKQUOTE>

When an <I>id-expression</I> (7.5.4 [expr.prim.id])
that is not part of a class member access syntax
(7.6.1.4 [expr.ref]) and not used to form a
pointer to member (7.6.2.1 [expr.unary.op]) is used in
a member of class <TT>X</TT> in a context
where <TT>this</TT> can be used
(7.5.2 [expr.prim.this]), if name lookup
(6.5 [basic.lookup]) resolves the name in
the <I>id-expression</I> to a non-static non-type member of
some class <TT>C</TT>, and if either
the <I>id-expression</I> is potentially evaluated
or <TT>C</TT> is <TT>X</TT> or a base class of <TT>X</TT>,
the <I>id-expression</I> is transformed into a class member
access expression (7.6.1.4 [expr.ref]) using
<TT>(*this)</TT> (11.4.2.1 [class.this]) as
the <I>postfix-expression</I> to the left of the
<TT>.</TT> operator. [<I>Note:</I> If <TT>C</TT> is
not <TT>X</TT> or a base class of<TT> X</TT>, the class
member access expression is ill-formed. &#8212;<I>end
note</I>] <SPAN style="text-decoration:line-through;background-color:#FFA0A0">Similarly during name lookup, when
an <I>unqualified-id</I> (7.5.4.1 [expr.prim.id.unqual]) used
in the definition of a member function for class <TT>X</TT>
resolves to a static member, an enumerator or a nested type
of class <TT>X</TT> or of a base class of <TT>X</TT>,
the <I>unqualified-id</I> is transformed into
a <I>qualified-id</I> (7.5.4.2 [expr.prim.id.qual]) in
which the <I>nested-name-specifier</I> names the class of
the member function. These transformations do</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">This transformation does</SPAN> not apply in the
template definition context
(13.8.2.1 [temp.dep.type]). [<I>Example:</I>...

</BLOCKQUOTE>

<LI><P>Delete 11.4.8 [class.static] paragraph 3:</P></LI>

<BLOCKQUOTE>

<SPAN style="text-decoration:line-through;background-color:#FFA0A0">If an unqualified-id (7.5.4.1 [expr.prim.id.unqual]) is used
in the definition of a static member following the
member's <I>declarator-id</I>, and name lookup
(6.5.1 [basic.lookup.unqual]) finds that
the <I>unqualified-id</I> refers to a static member,
enumerator, or nested type of the member's class (or of a
base class of the member's class), the <I>unqualified-id</I>
is transformed into a <I>qualified-id</I> expression in
which the <I>nested-name-specifier</I> names the class scope
from which the member is referenced. [<I>Note:</I> See
7.5.4 [expr.prim.id] for restrictions on the use of
non-static data members and non-static member
functions. &#8212;<I>end note</I>]</SPAN>

</BLOCKQUOTE>

<LI><P>Change 11.5.1 [class.union.anon] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

<P>A union of the form</P>

<UL><TT>union {</TT> <I>member-specification</I> <TT>} ;</TT>
</UL>

<P>is called an anonymous union; it defines an unnamed type
and an unnamed object of that type called an anonymous union
object. Each <I>member-declaration</I> in
the <I>member-specification</I> of an anonymous union shall
either define a non-static data member or be a
static_<I>assert-declaration</I>. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">[<I>Note:</I></SPAN>
Nested types, anonymous unions, and functions <SPAN style="text-decoration:line-through;background-color:#FFA0A0">cannot</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">shall not</SPAN> be declared within an anonymous
union. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">&#8212;<I>end note</I>]</SPAN> The names of the
members...</P>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2126"></A><H4>2126.
  
Lifetime-extended temporaries in constant expressions
</H4><B>Section: </B>7.7&#160; [expr.const]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2015-05-20




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

<PRE>
  typedef const int CI[3];
  constexpr CI &amp;ci = CI{11, 22, 33};
  static_assert(ci[1] == 22, "");
</PRE>

<P>This is ill-formed because the lifetime of the array temporary
did not start within the current evaluation.  Perhaps we should
treat all lifetime-extended temporaries of const-qualified literal
type that are initialized by constant expressions as if they are
<TT>constexpr</TT> objects?</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change 7.7 [expr.const] paragraph 3 as follows:</P>

<BLOCKQUOTE>

<P>A variable is <I>usable in constant expressions</I> after
its initializing declaration is encountered if it is a
constexpr variable, or it is a constant-initialized variable
of reference type or of const-qualified integral or
enumeration type. An object or reference is <I>usable in
constant expressions</I> if it is</P>

<UL><LI><P>a variable that is usable in constant
expressions, or</P></LI>

<LI><P>a template parameter object
(13.2 [temp.param]), or</P></LI>

<LI><P>a string literal object
(5.13.5 [lex.string]), or</P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">a temporary object of non-volatile const-qualified
literal type whose lifetime is extended
(6.7.7 [class.temporary]) to that of a variable that is usable
in constant expressions, or</SPAN></P></LI>

<LI><P>a non-mutable subobject or reference member of any of the
above<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, or</SPAN><SPAN style="font-weight:bold;background-color:#A0FFA0">.</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">a complete temporary object of non-volatile const-qualified
integral or enumeration type that is initialized with a
constant expression.</SPAN></P></LI>

</UL>

</BLOCKQUOTE>

<P>This resolution also resolves issue 2439.</P>

<BR><BR><HR><A NAME="2282"></A><H4>2282.
  
Consistency with mismatched aligned/non-over-aligned allocation/deallocation functions
</H4><B>Section: </B>7.6.2.7&#160; [expr.new]
 &#160;&#160;&#160;

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

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

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




<P>The fallback treatment for alignment and non-alignment
allocation and deallocation functions is asymmetric. While a
deletion of a non-overaligned class object will match a
class-specific alignment deallocation function if no
class-specific non-alignment deallocation function is
provided, the same is not true for allocation: a
<I>new-expression</I> for a non-overaligned class type will
fail if an alignment allocation function is provided with no
non-alignment allocation function. The allocation behavior
should be changed to match the deallocation behavior.</P>

<P><B>Proposed resolution (September, 2019):</B></P>

<P>Change 7.6.2.7 [expr.new] paragraph 18 as follows, splitting
the running text into bullets:</P>

<BLOCKQUOTE>

<P>Overload resolution is performed on a function call created
by assembling an argument list. The first argument is the
amount of space requested, and has type <TT>std::size_t</TT>. If the
type of the allocated object has new-extended alignment, the
next argument is the type's alignment, and has type
<TT>std::align_val_t</TT>. If the <I>new-placement</I> syntax is
used, the <I>initializer-clause</I>s in
its <I>expression-list</I> are the succeeding arguments.  If
no matching function is found <SPAN style="font-weight:bold;background-color:#A0FFA0">then</SPAN></P>

<UL><LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">and</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">if</SPAN> the allocated object
type has new-extended alignment, the alignment argument is
removed from the argument list<SPAN style="text-decoration:line-through;background-color:#FFA0A0">,</SPAN><SPAN style="font-weight:bold;background-color:#A0FFA0">;</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">otherwise, an argument list that is the type's alignment
and has type <TT>std::align_val_t</TT> is added into the argument
list immediately after the first argument;</SPAN></P></LI>

</UL>

<P>and <SPAN style="font-weight:bold;background-color:#A0FFA0">then</SPAN> overload resolution is performed
again.</P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2347"></A><H4>2347.
  
Passing short scoped enumerations to ellipsis
</H4><B>Section: </B>7.6.1.2&#160; [expr.call]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Mike Miller
 &#160;&#160;&#160;

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


<P>According to 7.6.1.2 [expr.call] paragraph 9,</P>

<BLOCKQUOTE>

If the argument has integral or enumeration type that is subject to the
integral promotions (7.3.6 [conv.prom]), or a floating-point type
that is subject to the floating-point promotion (7.3.7 [conv.fpprom]),
the value of the argument is converted to the promoted type before the
call. These promotions are referred to as the default argument promotions.

</BLOCKQUOTE>

<P>A scoped enumeration with an underlying type that is shorter than
<TT>int</TT> will not be widened when passed to an ellipsis. Should it
be?</P>

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

<P>The consensus of CWG was that the value passed ougnt to be widened
to match the promoted type of the underlying type.</P>

<P><B>Proposed resolution (May, 2019): [SUPERSEDED]</B></P>

<P>Change 7.6.1.2 [expr.call] paragraph 12 as follows:</P>

<BLOCKQUOTE>

...If the argument has <SPAN style="font-weight:bold;background-color:#A0FFA0">an</SPAN>
integral or enumeration type that is
subject to the integral promotions
(7.3.6 [conv.prom]), <SPAN style="font-weight:bold;background-color:#A0FFA0">a scoped enumeration type
whose underlying type is subject to the integral promotions,</SPAN>
or a floating-point type that
is subject to the floating-point promotion
(7.3.7 [conv.fpprom]), the value of the argument is
converted to the promoted type before the call. These
promotions are referred to as the <I>default argument
promotions</I>.

</BLOCKQUOTE>

<P><B>Notes from the September, 2019 teleconference:</B></P>

<P>The consensus was that passing scoped enumerations to ellipsis
should be conditionally-supported behavior, similar to the
treatment of class types with nontrivial copy semantics.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change 7.6.1.2 [expr.call] paragraph 12 as follows:</P>

<BLOCKQUOTE>

...Passing a potentially-evaluated argument of <SPAN style="font-weight:bold;background-color:#A0FFA0">a scoped
enumeration type or of a</SPAN> class type (Clause
11 [class]) having an eligible non-trivial copy
constructor, an eligible non-trivial move constructor, or a
non-trivial destructor (11.4.3 [special]), with
no corresponding parameter, is conditionally-supported with
implementation-defined semantics. If the argument...

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2374"></A><H4>2374.
  
Overly permissive specification of <TT>enum</TT> direct-list-initialization
</H4><B>Section: </B>9.4.4&#160; [dcl.init.list]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Shafik Yaghmour
 &#160;&#160;&#160;

 <B>Date: </B>2018-02-18


<P>According to 9.4.4 [dcl.init.list] bullet 3.8,</P>

<UL><LI>

<P>Otherwise, if <TT>T</TT> is an enumeration with a fixed
underlying type (9.7.1 [dcl.enum]),
the <I>initializer-list</I> has a single element <TT>v</TT>,
and the initialization is direct-list-initialization, the
object is initialized with the value <TT>T(v)</TT>
(7.6.1.3 [expr.type.conv]); if a narrowing conversion is
required to convert <TT>v</TT> to the underlying type
of <TT>T</TT>, the program is ill-formed.</P></LI>

</UL>

<P>The conversion <TT>T(v)</TT> is too broad, allowing, e.g.,
conversion from a different scoped enumeration type. The
intent presumably was only to allow <TT>v</TT> to be a value
of <TT>T</TT>'s underlying type.
</P>

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

<P>CWG agreed with the suggested direction, along the lines of
&#8220;...can be implicitly converted to the underlying type
of <TT>T</TT>...&#8221;</P>

<P><B>Proposed resolution (May, 2019): [SUPERSEDED]</B></P>

<P>Change bullet 3.8 of 9.4.4 [dcl.init.list] as follows:</P>

<UL><LI>

<P>Otherwise, if <TT>T</TT> is an enumeration with a fixed
underlying type (9.7.1 [dcl.enum]),
the <I>initializer-list</I> has a single
element <TT>v</TT>, <SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>v</TT> can be implicitly
converted to the underlying type of <TT>T</TT>,</SPAN> and
the initialization is direct-list-initialization, the object
is initialized with the value <TT>T(v)</TT>
(7.6.1.3 [expr.type.conv]); if a narrowing conversion is
required to convert <TT>v</TT> to the underlying type
of <TT>T</TT>, the program is
ill-formed. [<I>Example:</I>...</P></LI>

</UL>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change bullet 3.8 of 9.4.4 [dcl.init.list] as follows:</P>

<UL><LI>

<P>Otherwise, if <TT>T</TT> is an enumeration with a fixed
underlying type
(9.7.1 [dcl.enum]) <SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>U</TT></SPAN>,
the <I>initializer-list</I> has a single
element <TT>v</TT>, <SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>v</TT> can be implicitly
converted to <TT>U</TT>,</SPAN> and the initialization is
direct-list-initialization, the object is initialized with
the value <TT>T(v)</TT> (7.6.1.3 [expr.type.conv]); if a
narrowing conversion is required to convert <TT>v</TT> to
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">the underlying type of <TT>T</TT></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>U</TT></SPAN>, the program is
ill-formed. [<I>Example:</I>...</P></LI>

</UL>

<BR><BR><HR><A NAME="2399"></A><H4>2399.
  
Unclear referent of &#8220;expression&#8221; in <I>assignment-expression</I>
</H4><B>Section: </B>7.6.19&#160; [expr.ass]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Lisa Lippincott
 &#160;&#160;&#160;

 <B>Date: </B>2019-02-13



<P>According to 7.6.19 [expr.ass] paragraph 3,</P>

<BLOCKQUOTE>

If the left operand is not of class type, the expression is
implicitly converted (7.3 [conv]) to the
cv-unqualified type of the left operand.

</BLOCKQUOTE>

<P>Since the second operand of an assignment operator can now
be an <I>initializer-clause</I>, the referent of
&#8220;expression&#8221; is unclear.</P>

<P>See also issue 1542.</P>

<P><B>Proposed resolution (May, 2019): [SUPERSEDED]</B></P>

<P>Change 7.6.19 [expr.ass] paragraph 3 as follows:</P>

<BLOCKQUOTE>

If the left operand is not of class type <SPAN style="font-weight:bold;background-color:#A0FFA0">and the right
operand is an <I>assignment-expression</I></SPAN>,
the <SPAN style="text-decoration:line-through;background-color:#FFA0A0">expression</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0"><I>assignment-expression</I></SPAN>
is implicitly converted (7.3 [conv]) to the
cv-unqualified type of the left operand.

</BLOCKQUOTE>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change 7.6.19 [expr.ass] paragraph 3 as follows:</P>

<BLOCKQUOTE>

<SPAN style="text-decoration:line-through;background-color:#FFA0A0">The expression</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">If the right operand is an
expression, it</SPAN> is implicitly converted
(7.3 [conv]) to the cv-unqualified type of the
left operand.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2419"></A><H4>2419.
  
Loss of generality treating pointers to objects as one-element arrays
</H4><B>Section: </B>7.6.6&#160; [expr.add]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Andrey Erokhin
 &#160;&#160;&#160;

 <B>Date: </B>2019-07-15


CCCC,<P>Before the resolution of issue 1596,
7.6.6 [expr.add] specified that:</P>

<BLOCKQUOTE>

For the purposes of these operators, a pointer to a nonarray object
behaves the same as a pointer to the first element of an array of length
one with the type of the object as its element type.

</BLOCKQUOTE>

<P>where &#8220;these operators&#8221; refers to the additive operators.
This provision thus applied to any pointer, regardless of its
provenance. In its place, the normative provision for this treatment
was restricted to the <TT>&amp;</TT> operator only, in
7.6.2.1 [expr.unary.op] paragraph 3:</P>

<BLOCKQUOTE>

For purposes of pointer arithmetic (7.6.6 [expr.add]) and
comparison (7.6.9 [expr.rel],
7.6.10 [expr.eq]), an object that is not an array
element whose address is taken in this way is considered to
belong to an array with one element of type <TT>T</TT>.

</BLOCKQUOTE>

<P>Thus, for example:</P>

<PRE>
  int *p1 = new int;
  int *p2 = &amp;*p1;
  bool b1 = p1 &lt; p1+1;  //<SPAN style="font-family:Times;font-style:italic"> undefined behavior</SPAN>
  bool b2 = p2 &lt; p2+1;  //<SPAN style="font-family:Times;font-style:italic"> well-defined</SPAN>
</PRE>

<P>This restriction does not seem desirable.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<OL><LI><P>Change 7.6.2.1 [expr.unary.op] bullet 3.2 as follows:</P></LI>

<BLOCKQUOTE>

<P>The result of the unary <TT>&amp;</TT> operator is a pointer
to its operand.</P>

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

<LI><P>Otherwise, if the operand is an lvalue of type <TT>T</TT>, the
resulting expression is a prvalue of type &#8220;pointer to
<TT>T</TT>&#8221; whose result is a pointer to the designated object
(6.7.1 [intro.memory]) or function. [<I>Note:</I> In
particular, taking the address of a variable of type
&#8220;<I>cv</I>
<TT>T</TT>&#8221; yields a pointer of type &#8220;pointer
to <I>cv</I>
<TT>T</TT>&#8221;. &#8212;<I>end note</I>] <SPAN style="text-decoration:line-through;background-color:#FFA0A0">For purposes
of pointer arithmetic (7.6.6 [expr.add]) and
comparison (7.6.9 [expr.rel],
7.6.10 [expr.eq]), an object that is not an array
element whose address is taken in this way is considered to
belong to an array with one element of
type <TT>T</TT>.</SPAN></P></LI>

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

</UL>

</BLOCKQUOTE>

<LI><P>Change 6.8.2 [basic.compound] paragraph 3 as follows:</P></LI>

<BLOCKQUOTE>

...A value of a pointer type that is a pointer to or past
the end of an object <I>represents the address</I> of the
first byte in memory (6.7.1 [intro.memory]) occupied
by the object<SUP>43</SUP> or the first byte in memory after
the end of the storage occupied by the object,
respectively. [<I>Note:</I> A pointer past the end of an
object (7.6.6 [expr.add]) is not considered to
point to an unrelated object of the object's type that might
be located at that address. A pointer value becomes invalid
when the storage it denotes reaches the end of its storage
duration; see 6.7.5 [basic.stc]. &#8212;<I>end
note</I>] For purposes of pointer arithmetic
(7.6.6 [expr.add]) and comparison
(7.6.9 [expr.rel], 7.6.10 [expr.eq]), a
pointer past the end of the last element of an
array <TT>x</TT> of <I>n</I> elements is considered to be
equivalent to a pointer to a hypothetical
element <TT>x[</TT><I>n</I><TT>]</TT> <SPAN style="font-weight:bold;background-color:#A0FFA0">and an object
of type <TT>T</TT> that is not an array element is considered
to belong to an array with one element of
type <TT>T</TT></SPAN>. The value representation of pointer
types...

</BLOCKQUOTE>

<LI><P>Change the footnote in 7.6.6 [expr.add] bullet 4.2
as follows:</P></LI>

<BLOCKQUOTE>

<P>When an expression <TT>J</TT> that has integral type is
added to or subtracted from an expression <TT>P</TT> of
pointer type, the result has the type of <TT>P</TT>.</P>

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

<LI><P>Otherwise, if <TT>P</TT> points to an array
element <I>i</I> of an array object <TT>x</TT> with <I>n</I>
elements (9.3.3.4 [dcl.array]), [<I>Footnote:</I>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">An</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">As specified in
6.8.2 [basic.compound].  an</SPAN> object that is not an
array element is considered to belong to a single-element
array for this purpose<SPAN style="text-decoration:line-through;background-color:#FFA0A0">; see
7.6.2.1 [expr.unary.op]. A</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">and a</SPAN> pointer past the last element of an
array <TT>x</TT> of <I>n</I> elements is considered to be
equivalent to a pointer to a hypothetical array
element <I>n</I> for this purpose<SPAN style="text-decoration:line-through;background-color:#FFA0A0">; see
6.8.2 [basic.compound]</SPAN>.  &#8212;<I>end
footnote</I>] the expressions...</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change the footnote in 7.6.9 [expr.rel] paragraph
4 aa follows:</P></LI>

<BLOCKQUOTE>

The result of comparing unequal pointers to objects
[<I>Footnote:</I> <SPAN style="text-decoration:line-through;background-color:#FFA0A0">An</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">As specified in 6.8.2 [basic.compound], an</SPAN>
object that is not an array element is
considered to belong to a single-element array for this
purpose<SPAN style="text-decoration:line-through;background-color:#FFA0A0">; see 7.6.2.1 [expr.unary.op]. A</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">and a</SPAN> pointer past the last element of an
array <TT>x</TT> of <I>n</I> elements is considered to be
equivalent to a pointer to a hypothetical <SPAN style="font-weight:bold;background-color:#A0FFA0">array</SPAN>
element <SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>x [</TT> <I>n</I> <TT>]</TT></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><I>n</I></SPAN> for this purpose<SPAN style="text-decoration:line-through;background-color:#FFA0A0">; see
6.8.2 [basic.compound]</SPAN>.  &#8212;<I>end footnote</I>] is
defined in terms of a partial order consistent with the
following rules:

</BLOCKQUOTE>

<LI><P>Change 25.9.15 [numeric.ops.midpoint] paragraph 5 as follows:</P></LI>

<BLOCKQUOTE>

<I>Expects:</I> <TT>a</TT> and <TT>b</TT> point to,
respectively, elements <TT>x[</TT><I>i</I><TT>]</TT>
and <TT>x[</TT><I>j</I><TT>]</TT> of the same array object
<TT>x</TT>. [<I>Note:</I> <SPAN style="text-decoration:line-through;background-color:#FFA0A0">An</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">As specified in 6.8.2 [basic.compound], an</SPAN>
object that is not an array element is considered to belong
to a single-element array for this purpose<SPAN style="text-decoration:line-through;background-color:#FFA0A0">; see
7.6.2.1 [expr.unary.op]. A</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">and a</SPAN> pointer past the last element of an
array <TT>x</TT> of <I>n</I> elements is considered to be
equivalent to a pointer to a hypothetical <SPAN style="font-weight:bold;background-color:#A0FFA0">array</SPAN>
element <SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>x[</TT><I>n</I><TT>]</TT></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><I>n</I></SPAN> for this purpose<SPAN style="text-decoration:line-through;background-color:#FFA0A0">; see
6.8.2 [basic.compound]</SPAN>. &#8212;<I>end note</I>]

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2422"></A><H4>2422.
  
Incorrect grammar for <I>deduction-guide</I>
</H4><B>Section: </B>13.11&#160; [temp.deduct.guide]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Barry Revzin
 &#160;&#160;&#160;

 <B>Date: </B>2019-07-28


<P>According to 13.11 [temp.deduct.guide] paragraph 1, the syntax of
a <I>deduction-guide</I> is:</P>

<UL><I>deduction-guide:</I>
<UL><TT>explicit</TT><I><SUB>opt</SUB> template-name</I> <TT>(</TT><I> parameter-declaration-clause</I> <TT>) -&gt;</TT> <I>simple-template-id</I> <TT>;</TT>
</UL>
</UL>

<P>Instead of <TT>explicit</TT>, this production should use the
<I>explicit-specifier</I> nonterminal. (The wording of
12.4.1.8 [over.match.class.deduct] has references to the
<I>explicit-specifier</I> of a deduction guide, for example.)</P>

<P><B>Proposed resolution (September, 2019):</B></P>

<P>Change the grammar in 13.11 [temp.deduct.guide] paragraph 1 as
follows:</P>

<UL><I>deduction-guide:</I>
<UL><SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>explicit</TT></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><I>explicit-specifier</I></SPAN><I><SUB>opt</SUB> template-name </I><TT>(</TT><I> parameter-declaration-clause </I><TT>) -&gt;</TT><I> simple-template-id </I><TT>;</TT>
</UL>
</UL>

<BR><BR><HR><A NAME="2424"></A><H4>2424.
  
<TT>constexpr</TT> initialization requirements for variant members
</H4><B>Section: </B>9.2.5&#160; [dcl.constexpr]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2019-08-03




<P>Paper <A HREF="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1331r2.pdf">P1331R2</A>
removed the requirement that a constexpr constructor
initialize every non-variant non-static data member, but it
left untouched the corresponding requirements for variant
members.  That is, the modified text in 9.2.5 [dcl.constexpr]
paragraph 4 still contains:</P>

<BLOCKQUOTE>

<P>The definition of a constexpr constructor
whose <I>function-body</I> is not <TT>= delete</TT> shall
additionally satisfy the following requirements:</P>

<UL><LI><P>if the class is a union having variant members
(11.5 [class.union]), exactly one of them shall be
initialized;</P></LI>

<LI><P>if the class is a union-like class, but is not a
union, for each of its anonymous union members having
variant members, exactly one of them shall be
initialized;</P></LI>

</UL>

</BLOCKQUOTE>

<P>Presumably this was an oversight and these two bullets
should be changed from &#8220;exactly&#8221; to &#8220;at
most&#8221; or something similar.</P>

<P><B>Proposed resolution (September, 2019):</B></P>

<P>Delete the indcated text from 9.2.5 [dcl.constexpr] paragraph 4:</P>

<BLOCKQUOTE>

<P>The definition of a constexpr constructor
whose <I>function-body</I> is not <TT>= delete</TT> shall
additionally satisfy the following requirements:</P>

<UL><LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">if the class is a union having variant members
(11.5 [class.union]), exactly one of them shall be
initialized;</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">if the class is a union-like class, but is not a union, for
each of its anonymous union members having variant members,
exactly one of them shall be initialized;</SPAN>
</P></LI>

<LI><P>for a non-delegating constructor, every constructor selected
to initialize non-static data members and base class
subobjects shall be a constexpr constructor;</P></LI>

<LI><P>for a delegating constructor, the target constructor shall
be a constexpr constructor.</P></LI>

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2426"></A><H4>2426.
  
Reference to destructor that cannot be invoked
</H4><B>Section: </B>14.3&#160; [except.ctor]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Mike Miller
 &#160;&#160;&#160;

 <B>Date: </B>2019-08-13


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

<PRE>
   template&lt;typename T&gt; struct A {
   private:
     ~A() {}
   };
   A&lt;char&gt; g();
   A&lt;char&gt; f() { return g(); }
</PRE>

<P>According to 14.3 [except.ctor] paragraph 2,</P>

<BLOCKQUOTE>

If an exception is thrown during the destruction of
temporaries or local variables for a <TT>return</TT>
statement (8.7.3 [stmt.return]), the destructor for
the returned object (if any) is also invoked.

</BLOCKQUOTE>

<P>In <TT>f()</TT> there is no possibility of an exception
occuring during the processing of the <TT>return</TT>
statement, so there appears to be no reason for a reference
to the private destructor of <TT>A&lt;char&gt;</TT>. Current
implementations, however, issue an access error for this
example. Is wording needed to make that destructor potentially
invoked in such cases?</P>

<P><B>Proposed resolution (September, 2019):</B></P>

<OL><LI><P>Change 8.7.3 [stmt.return] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

<P>...[<I>Note:</I> A <TT>return</TT> statement can involve
an invocation of a constructor to perform a copy or move of
the operand if it is not a prvalue or if its type differs
from the return type of the function. A copy operation
associated with a <TT>return</TT> statement may be elided or
converted to a move operation if an automatic storage
duration variable is returned
(11.10.5 [class.copy.elision]).  &#8212;<I>end note</I>]
[<I>Example:</I></P>

<PRE>
  std::pair&lt;std::string,int&gt; f(const char* p, int x) {
    return {p,x};
  }
</PRE>

&#8212;<I>end example</I>]
<SPAN style="font-weight:bold;background-color:#A0FFA0">The destructor for the returned object is potentially
invoked (11.4.6 [class.dtor],
14.3 [except.ctor]). [<I>Example:</I></SPAN>

<PRE>
<SPAN style="font-weight:bold;background-color:#A0FFA0">  class A {
    ~A() {}
  };
  A f() { return A(); }   //<SPAN style="font-family:Times;font-style:italic"> error: destructor of </SPAN>A<SPAN style="font-family:Times;font-style:italic"> is private (even though it is never invoked)</SPAN></SPAN>
</PRE>

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

Flowing off the end...

</BLOCKQUOTE>

<LI><P>Change 11.4.6 [class.dtor] paragraph 14 as follows:</P></LI>

<BLOCKQUOTE>

A destructor can also be invoked explicitly. A destructor is
potentially invoked if it is invoked or as specified in
7.6.2.7 [expr.new], <SPAN style="font-weight:bold;background-color:#A0FFA0">8.7.3 [stmt.return],</SPAN>
9.4.1 [dcl.init.aggr], 11.10.2 [class.base.init],
and 14.2 [except.throw]. A program is ill-formed if a
destructor that is potentially invoked is deleted or not
accessible from the context of the invocation.

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2427"></A><H4>2427.
  
Deprecation of volatile operands and unevaluated contexts
</H4><B>Section: </B>7.6.19&#160; [expr.ass]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Mike Miller
 &#160;&#160;&#160;

 <B>Date: </B>2019-08-14


<P>According to 7.6.19 [expr.ass] paragraph 7,</P>

<BLOCKQUOTE>

A simple assignment whose left operand is of a volatile
-qualified non-class type is deprecated
(D.5 [depr.volatile.type]) unless the assignment is either a
discarded-value expression or appears in an unevaluated
context.

</BLOCKQUOTE>

<P>The deprecations of increment, decrement, and compound
assignment operators do not, but presumably should, mention
unevaluated contexts.</P>

<P><B>Notes from the August, 2019 teleconference:</B></P>

<P>The omission of those operators was intentional; the deprecation
is intended only to affect cases where using the result of the
operation would result in a subsequent fetch of the value. However,
some shortcomings of the existing wording were noted and will be
addressed in the resolution.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change 7.6.19 [expr.ass] paragraph 5 as follows:</P>

<BLOCKQUOTE>

A simple assignment whose left operand is of
a <TT>volatile</TT>-qualified type is deprecated
(D.5 [depr.volatile.type]) unless the <SPAN style="font-weight:bold;background-color:#A0FFA0">(possibly
parenthesized)</SPAN> assignment is <SPAN style="text-decoration:line-through;background-color:#FFA0A0">either</SPAN>
a discarded-value expression or <SPAN style="text-decoration:line-through;background-color:#FFA0A0">appears in</SPAN>
an unevaluated <SPAN style="text-decoration:line-through;background-color:#FFA0A0">context</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">operand</SPAN>.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2429"></A><H4>2429.
  
Initialization of <TT>thread_local</TT> variables referenced by lambdas
</H4><B>Section: </B>8.8&#160; [stmt.dcl]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Princeton Ferro
 &#160;&#160;&#160;

 <B>Date: </B>2019-08-22


<P>According to 6.7.5.2 [basic.stc.thread] paragraph 2,</P>

<BLOCKQUOTE>

A variable with thread storage duration shall be initialized before its
first odr-use (6.3 [basic.def.odr]) and, if constructed, shall be
destroyed on thread exit.

</BLOCKQUOTE>

<P>According to 8.8 [stmt.dcl] paragraph 4, for
block-scope variables this initialization is peformed when the
declaration statement is executed:</P>

<BLOCKQUOTE>

Dynamic initialization of a block-scope variable with static
storage duration (6.7.5.1 [basic.stc.static]) or thread
storage duration (6.7.5.2 [basic.stc.thread]) is performed
the first time control passes through its declaration; such
a variable is considered initialized upon the completion of
its initialization.

</BLOCKQUOTE>

<P>However, there are cases in which the flow of control does
not pass through a variable's declaration, leaving it
uninitialized in spite of it being odr-used. For example:</P>

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

  struct Object {
    int i;
    Object() : i(3) {}
  };

  int main(void) {
    static thread_local Object o;

    std::cout &lt;&lt; "[main] o.i = " &lt;&lt; o.i &lt;&lt; std::endl;
    std::thread([] {
      std::cout &lt;&lt; "[new thread] o.i = " &lt;&lt; o.i &lt;&lt; std::endl;
    }).join();
  }

</PRE>

<P><TT>o</TT> is a block-scope variable with thread storage
and a dynamic initializer. The lambda passed
into <TT>std::thread</TT>'s constructor refers to o<TT></TT>
but does not capture it, which should be fine
since <TT>o</TT> is not a variable with automatic storage.
However, when control passes through the lambda, it will do
so on a new thread. When that happens, it will refer
to <TT>o</TT> for the first time. Because <TT>o</TT> is a
thread-local variable, it should be initialized, but because
it is declared in block scope, it will only be initialized
when control passes through its declaration, which will
never happen on the new thread.</P>

<P>This example is straightforward, but others are more
ambiguous:</P>

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

  struct Object {
    int i;
    Object(int v) : i(3 + v) {}
  };

  int main(void) {
    int w = 4;
    static thread_local Object o(w);

    std::cout &lt;&lt; "[main] o.i = " &lt;&lt; o.i &lt;&lt; std::endl;
    std::thread([] {
      std::cout &lt;&lt; "[new thread] o.i = " &lt;&lt; o.i &lt;&lt; std::endl;
    }).join();
  }
</PRE>

<P>Here the initialization of <TT>o</TT> uses the value of <TT>w</TT>,
which is not captured. Perhaps it should be ill-formed for a lambda
to refer to a block-scope thread-local variable.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change 6.7.5.2 [basic.stc.thread] paragraphs 1 and 2 as follows:</P>



<BLOCKQUOTE>

<P>All variables declared with the <TT>thread_local</TT>
keyword have <I>thread storage duration</I>. The storage
for these entities <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall last</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">lasts</SPAN>
for the duration of the thread in which they are
created. There is a distinct object or reference per thread,
and use of the declared name refers to the entity associated
with the current thread.</P>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">[<I>Note:</I></SPAN> A variable with thread storage
duration <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall be</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">is</SPAN>
initialized <SPAN style="text-decoration:line-through;background-color:#FFA0A0">before its first odr-use
(6.3 [basic.def.odr])</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">as specified in 6.9.3.2 [basic.start.static],
6.9.3.3 [basic.start.dynamic], and
8.8 [stmt.dcl]</SPAN> and, if
constructed, <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall be</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">is</SPAN> destroyed on
thread exit <SPAN style="font-weight:bold;background-color:#A0FFA0">(6.9.3.4 [basic.start.term])</SPAN>.
<SPAN style="font-weight:bold;background-color:#A0FFA0">&#8212;<I>end note</I>]</SPAN></P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2430"></A><H4>2430.
  
Completeness of return and parameter types of member functions
</H4><B>Section: </B>11.4&#160; [class.mem]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Krystian Stasiowski
 &#160;&#160;&#160;

 <B>Date: </B>2019-08-23


<P>According to 11.4 [class.mem] paragraph 7,</P>

<BLOCKQUOTE>

A class is considered a completely-defined object type
(6.8 [basic.types]) (or complete type) at the closing
} of the <I>class-specifier</I>. The class is regarded as
complete within its complete-class contexts; otherwise it is
regarded as incomplete within its own
class <I>member-specification</I>.

</BLOCKQUOTE>

<P>The complete-class contexts (paragraph 6) include the body
of a member function but not its return and parameter types.
Thus it appears that an example like the following is
ill-formed:</P>

<PRE>
  struct S {
    S f(S s) { return s; }
  };
</PRE>

<P>because of 9.5.1 [dcl.fct.def.general] paragraph 2</P>

<BLOCKQUOTE>

The type of a parameter or the return type for a function
definition shall not be an incomplete or abstract (possibly
cv-qualified) class type in the context of the function
definition unless the function is deleted
(9.5.3 [dcl.fct.def.delete]).

</BLOCKQUOTE>

<P>The words &#8220;in the context of the function
definition&#8221; were added by the resolution of
issue 1824 to address this
problem, but &#8220;context&#8221; is most naturally
read as referring to the lexical context where the
definition appears rather than within its body.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change 9.5.1 [dcl.fct.def.general] paragraph 2 as follows:</P>

<BLOCKQUOTE>

...The type of a parameter or the return type for a function
definition shall not be <SPAN style="text-decoration:line-through;background-color:#FFA0A0">an incomplete or abstract
(possibly cv-qualified) class type in the context of the
function definition</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">a (possibly cv-qualified)
class type that is incomplete or abstract within the
function body</SPAN> unless the function is deleted
(9.5.3 [dcl.fct.def.delete]).

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2431"></A><H4>2431.
  
Full-expressions and temporaries bound to references
</H4><B>Section: </B>6.9&#160; [basic.exec]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Andrey Erokhin
 &#160;&#160;&#160;

 <B>Date: </B>2019-02-07


<P>According to 6.9 [basic.exec] paragraph 5,</P>

<BLOCKQUOTE>

<P>A <I>full-expression</I> is</P>

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

<LI><P>an invocation of a destructor generated at the end of
the lifetime of an object other than a temporary object
(6.7.7 [class.temporary]), or</P></LI>

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

</UL>

</BLOCKQUOTE>

<P>This definition excludes the destruction of temporaries
that are bound to references from being treated as
full-expressions. It is not clear whether this omission has
observable effects or not. See
<A HREF="https://github.com/cplusplus/draft/issues/2664">
editorial issue 2664</A>.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change 6.9 [basic.exec] bullet 5.5 as follows:</P>

<BLOCKQUOTE>


<P>A <I>full-expression</I> is</P>

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

<LI><P>an invocation of a destructor generated at the end of the
lifetime of an object other than a temporary object
(6.7.7 [class.temporary]) <SPAN style="font-weight:bold;background-color:#A0FFA0">whose lifetime has not been
extended</SPAN>, or</P></LI>

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

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2432"></A><H4>2432.
  
Return types for defaulted <TT>&lt;=&gt;</TT>
</H4><B>Section: </B>11.11.3&#160; [class.spaceship]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2019-08-14


<P>It is unclear what the constraints are on the type R.  We
define the "synthesized three-way comparison for comparison
category type R", but it's defined in such a way that it
works for an arbitrary type R, and the uses of it do not
impose a constraint that R is a comparison category
type. Should it be permissible to default
an <TT>operator&lt;=&gt;</TT> with some other return type,
so long as the construction described in
11.11.3 [class.spaceship] works (specifically, so long as
all subobjects have <TT>operator&lt;=&gt;</TT>s that can be
converted to the specified return type)?</P>

<P><B>Proposed resolution (September, 2019)</B></P>

<P>Change 11.11.3 [class.spaceship] paragraphs 1-3, changing the
running text of paragraph 2 to into a bulleted list, as follows:</P>

<BLOCKQUOTE>

<P>The <I>synthesized three-way comparison</I>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">for comparison category</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">of</SPAN>
type <TT>R</TT> (17.11.2 [cmp.categories]) of
glvalues <TT>a</TT> and <TT>b</TT>...</P>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">Let <TT>R</TT> be the declared return type of a
defaulted three-way comparison operator function.</SPAN>
Given an expanded list of subobjects for an
object <TT>x</TT> of
type <TT>C</TT>, <SPAN style="font-weight:bold;background-color:#A0FFA0">let <TT>R</TT><I><SUB>i</SUB></I> be</SPAN>
the type of the expression <TT>x</TT><I><SUB>i</SUB></I>
<TT>&lt;=&gt; x</TT><I><SUB>i</SUB></I><SPAN style="text-decoration:line-through;background-color:#FFA0A0"> is denoted
by <TT>R</TT><I><SUB>i</SUB></I>. If</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">, or <TT>void</TT> if</SPAN> overload resolution <SPAN style="text-decoration:line-through;background-color:#FFA0A0">as</SPAN>
applied to <SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>x</TT><I><SUB>i</SUB></I>
<TT>&lt;=&gt; x</TT><I><SUB>i</SUB></I></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">that expression</SPAN> does not find a usable
function<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, then <TT>R</TT><I><SUB>i</SUB></I>
is <TT>void</TT></SPAN>.</P>

<UL><LI><P>If <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the declared return type of a
defaulted three-way comparison operator function</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>R</TT></SPAN> is <TT>auto</TT>, then the return type
is deduced as the common comparison type (see below)
of <TT>R</TT><I><SUB>0</SUB></I>,
<TT>R</TT><I><SUB>1</SUB></I>,
..., <TT>R</TT><I><SUB>n-1</SUB></I>. If the return type is
deduced as <TT>void</TT>, the operator function is defined
as deleted.</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">If the declared return type of a defaulted
three-way comparison operator function is <TT>R</TT> and</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">Otherwise, if</SPAN> the synthesized three-way
comparison <SPAN style="text-decoration:line-through;background-color:#FFA0A0">for comparison category</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">of</SPAN> type <TT>R</TT> between any
objects <TT>x</TT><I><SUB>i</SUB></I>
and <TT>x</TT><I><SUB>i</SUB></I> is not defined or would be
ill-formed, the operator function is defined as deleted.</P></LI>

</UL>

<P>...until the first index <I>i</I> where the synthesized
three-way comparison <SPAN style="text-decoration:line-through;background-color:#FFA0A0">for comparison category</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">of</SPAN> type <TT>R</TT>
between <TT>x</TT><I><SUB>i</SUB></I>
and <TT>y</TT><I><SUB>i</SUB></I> yields...</P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2433"></A><H4>2433.
  
Variable templates in the ODR
</H4><B>Section: </B>6.3&#160; [basic.def.odr]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2019-10-10


<P>The list of entities in 6.3 [basic.def.odr] paragraph 12
that can have multiple definitions across translation units does
not, but should, include variable templates.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<BLOCKQUOTE>

<P>There can be more than one definition of a</P>

<UL><LI><P>class type (Clause 11 [class]),</P></LI>

<LI><P>enumeration type (9.7.1 [dcl.enum]),</P></LI>

<LI><P>inline function <SPAN style="font-weight:bold;background-color:#A0FFA0">or variable</SPAN>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">with external linkage</SPAN>
(9.2.7 [dcl.inline]),</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">inline variable with external linkage
(9.2.7 [dcl.inline]),</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">class template (Clause 13 [temp]),</SPAN>
</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">non-static function template
(13.7.6 [temp.fct]),</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">concept (13.7.8 [temp.concept]),</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">static data member of a class template
(13.7.1.3 [temp.static]),</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">member function of a class template
(13.7.1.1 [temp.mem.func]),</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">template specialization for which some template parameters
are not specified (13.9 [temp.spec],
13.7.5 [temp.class.spec]),</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">templated entity (13.1 [temp.pre]),</SPAN></P></LI>

<LI><P>default argument for a parameter (for a function in a
given scope), or</P></LI>

<LI><P>default template argument</P></LI>

</UL>

<P>in a program provided that...</P>

</BLOCKQUOTE>

<I>[Drafting note: &#8220;with external linkage&#8221; is
not needed for the </I><TT>inline</TT><I> entities because the
other cases - entities attached to a named module and
multiple definitions in the same translation unit - are
ruled out later in that paragraph.]</I>

<BR><BR><HR><A NAME="2437"></A><H4>2437.
  
Conversion of <TT>std::strong_ordering</TT> in a defaulted <TT>operator&lt;=&gt;</TT>
</H4><B>Section: </B>11.11.3&#160; [class.spaceship]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2019-08-14


<P>According to 11.11.3 [class.spaceship] paragraph 3,</P>

<BLOCKQUOTE>

The return value <TT>V</TT> of type <TT>R</TT> of the
defaulted three-way comparison operator function with
parameters <TT>x</TT> and <TT>y</TT> of the same type is
determined by comparing corresponding elements
<TT>x</TT><I><SUB>i</SUB></I>
and <TT>y</TT><I><SUB>i</SUB></I> in the expanded lists of
subobjects for <TT>x</TT> and <TT>y</TT> (in increasing
index order) until the first index <I>i</I> where the
synthesized three-way comparison for comparison category
type <TT>R</TT> between <TT>x</TT><I><SUB>i</SUB></I>
and <TT>y</TT><I><SUB>i</SUB></I> yields a result
value <TT>v</TT><I><SUB>i</SUB></I>
where <TT>v</TT><I><SUB>i</SUB></I>
<TT>!=</TT> 0, contextually converted to <TT>bool</TT>,
yields <TT>true</TT>; <TT>V</TT>
is <TT>v</TT><I><SUB>i</SUB></I>
converted to <TT>R</TT>. If no such
index exists, <TT>V</TT>
is <TT>std::strong_ordering::equal</TT>
converted to
<TT>R</TT>.

</BLOCKQUOTE>

<P>This is meaningless, however, because the kind of conversion
is not specified. According to bullet 1.1,</P>

<UL><LI><P>If overload resolution for <TT>a &lt;=&gt; b</TT>
finds a usable
function (12.4 [over.match]), <TT>static_cast&lt;R&gt;(a
&lt;=&gt; b)</TT>.</P></LI>

</UL>

<P>so consistency would suggest that
<TT>static_cast&lt;R&gt;(std::strong_ordering::equal)</TT> is
probably the right answer.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change 11.11.3 [class.spaceship] paragraph 3 as follows:</P>

<BLOCKQUOTE>

...If no such index exists, <TT>V</TT> is
<SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>static_cast&lt;R&gt;(</TT></SPAN><TT>std::strong_ordering::equal</TT><SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>)</TT></SPAN>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">converted to <TT>R</TT></SPAN>.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2439"></A><H4>2439.
  
Undefined term in definition of &#8220;usable in constant expressions&#8221;
</H4><B>Section: </B>7.7&#160; [expr.const]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Davis Herring
 &#160;&#160;&#160;

 <B>Date: </B>2019-08-28


<P>According to 7.7 [expr.const] paragraph 3,</P>

<BLOCKQUOTE>

<P>An object or reference is <I>usable in constant
expressions</I> if it is</P>

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

<LI><P>a complete temporary object of non-volatile const-qualified
integral or enumeration type that is initialized with a
constant expression.</P></LI>

</UL>

</BLOCKQUOTE>

<P>The phrase &#8220;initialized with a constant expression&#8221;
is not defined (which causes problems with
<TT>std::is_constant_evaluated</TT>). It would be better to use
&#8220;is constant-initialized&#8221; instead.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>This issue is resolved by the resolution of
issue 2126.</P>

<BR><BR><HR><A NAME="2442"></A><H4>2442.
  
Incorrect requirement for default arguments
</H4><B>Section: </B>12.4.2&#160; [over.match.viable]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>S. B. Tam
 &#160;&#160;&#160;

 <B>Date: </B>2019-09-24


<P>(From editorial issue
<A HREF="https://github.com/cplusplus/draft/issues/3235">3235</A>.)</P>

<P>According to 12.4.2 [over.match.viable] bullet 2.3 says,</P>

<BLOCKQUOTE>

<P>First, to be a viable function, a candidate function shall
have enough parameters to agree in number with the arguments
in the list.</P>

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

<LI><P>A candidate function having more than <I>m</I>
parameters is viable only if the <I>(m+1)</I><SUP>st</SUP>
parameter has a default argument
(9.3.3.6 [dcl.fct.default]).  [<I>Footnote:</I> According
to 9.3.3.6 [dcl.fct.default], parameters following
the <I>(m+1)</I><SUP>st</SUP> parameter must also have
default arguments. &#8212;<I>end footnote</I>] For the
purposes of overload resolution, the parameter list is
truncated on the right, so that there are exactly <I>m</I>
parameters.</P></LI>

</UL>

</BLOCKQUOTE>

<P>However, this is incorrect; 9.3.3.6 [dcl.fct.default]
paragraph 4 permits parameter packs to follow parameters with
default arguments.</P>

<P><B>Proposed resolution (October, 2019):</B></P>

<P>Change 12.4.2 [over.match.viable] bullet 2.3 as follows:</P>

<BLOCKQUOTE>

<UL><LI><P>A candidate function having more than <I>m</I>
parameters is viable only if <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the <I>(m+1)</I><SUP>st</SUP>
parameter has a default argument
(9.3.3.6 [dcl.fct.default]).  [<I>Footnote:</I> According
to 9.3.3.6 [dcl.fct.default], parameters following
the <I>(m+1)</I><SUP>st</SUP> parameter must also have
default arguments. &#8212;<I>end footnote</I>]</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">all parameters following the <I>m</I><SUP>th</SUP> have
default arguments (9.3.3.6 [dcl.fct.default]).</SPAN> For
the purposes of overload resolution, the parameter list is
truncated on the right, so that there are exactly <I>m</I>
parameters.</P></LI>

</UL>

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