<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;P1359R0</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Date:
     </TD>
<TD>
      &#160;2019-02-21</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
     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="581"></A><H4>581.
  
Can a templated constructor be explicitly instantiated or specialized?
</H4><B>Section: </B>12.9.1&#160; [temp.arg.explicit]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Mark Mitchell
 &#160;&#160;&#160;

 <B>Date: </B>19 May 2006


<P>Although it is not possible to specify a constructor's template
arguments in a constructor invocation (because the constructor has
no name but is invoked by use of the constructor's class's name), it
is possible to &#8220;name&#8221; the constructor in declarative
contexts: per 6.4.3.1 [class.qual] paragraph 2,</P>

<BLOCKQUOTE>

In a lookup in which the constructor is an acceptable lookup result,
if the <I>nested-name-specifier</I> nominates a class <TT>C</TT>, and
the name specified after the <I>nested-name-specifier</I>, when looked
up in <TT>C</TT>, is the injected-class-name of <TT>C</TT> (clause
10 [class]), the name is instead considered to name the
constructor of class <TT>C</TT>... Such a constructor name shall be
used only in the <I>declarator-id</I> of a declaration that names a
constructor.

</BLOCKQUOTE>

<P>Should it therefore be possible to specify <I>template-argument</I>s
for a templated constructor in an explicit instantiation or specialization?
For example,</P>

<PRE>
    template &lt;int dim&gt; struct T {};
    struct X {
      template &lt;int dim&gt; X (T&lt;dim&gt; &amp;) {};
    };

    template X::X&lt;&gt; (T&lt;2&gt; &amp;);
</PRE>

<P>If so, that should be clarified in the text.  In
particular, 10.3.4 [class.ctor] paragraph 1 says,</P>

<BLOCKQUOTE>

Constructors do not have names. A special declarator syntax using an
optional sequence of <I>function-specifier</I>s (9.1.2 [dcl.fct.spec]) followed by the constructor's class name followed by
a parameter list is used to declare or define the constructor.

</BLOCKQUOTE>

<P>This certainly sounds as if the parameter list must immediately
follow the class name, with no allowance for a template argument
list.</P>

<P>It would be worthwhile in any event to revise this wording
to utilize the &#8220;considered to name&#8221; approach of
6.4.3.1 [class.qual]; as it stands, this wording
sounds as if the following would be acceptable:</P>

<PRE>
    struct S {
        S();
    };
    S() { }    // <SPAN style="font-family:Times;font-style:italic">qualified-id</SPAN> not required?
</PRE>

<P><B>Notes from the October, 2006 meeting:</B></P>

<P>It was observed that explicitly specifying the template arguments
in a constructor declaration is never actually necessary because the
arguments are, by definition, all deducible and can thus be omitted.</P>

<P><B>Additional notes, October, 2018:</B></P>

<P>The wording in 12.9.1 [temp.arg.explicit] paragraph 1 refers to
a &#8220;function name,&#8221; which constructors do not have, and so
presumably the current wording does not permit an explicit specialization
of a constructor template. Nevertheless, there is implementation
divergence in the treatment of an example like:</P>

<PRE>
  class C {
    template &lt;typename T&gt;
    C(const T &amp;) {}
  };
  template C::C&lt;double&gt;(const double &amp;);
</PRE>

<P>with some accepting and some rejecting.</P>

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

<P>The consensus was to allow template arguments on the constructor
name but not something like <TT>C&lt;int&gt;::C&lt;float&gt;::f</TT>.</P>

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

<OL><LI><P>Cbange 12.9.1 [temp.arg.explicit] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

Template arguments can be specified when referring to a
function template specialization <SPAN style="font-weight:bold;background-color:#A0FFA0">that is not a
specialization of a constructor template</SPAN> by qualifying
the function template name with the list
of <I>template-argument</I>s in the same way
as <I>template-argument</I>s are specified in uses of a
class template specialization. [<I>Example:</I>

</BLOCKQUOTE>

<LI><P>Add the following as a new paragraph following
12.9.1 [temp.arg.explicit] paragraph 1:</P></LI>

<BLOCKQUOTE>

<SPAN style="font-weight:bold;background-color:#A0FFA0">Template arguments shall not be specified when
referring to a specialization of a constructor template
(10.3.4 [class.ctor],
6.4.3.1 [class.qual]).</SPAN>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="1937"></A><H4>1937.
  
Incomplete specification of function pointer from lambda
</H4><B>Section: </B>7.5.5&#160; [expr.prim.lambda]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2014-06-05




<P>According to 7.5.5 [expr.prim.lambda] paragraph 6,</P>

<BLOCKQUOTE>

The closure type for a non-generic <I>lambda-expression</I> with
no <I>lambda-capture</I> has a public non-virtual non-explicit
const conversion function to pointer to function with C ++
language linkage (9.10 [dcl.link]) having the same
parameter and return types as the closure type's function call
operator. The value returned by this conversion function shall be
the address of a function that, when invoked, has the same effect
as invoking the closure type's function call operator.

</BLOCKQUOTE>

<P>This does not mention the object for which the function call
operator would be invoked (although since there is no capture,
presumably the function call operator makes no use of the
object pointer).  This could be addressed by relating the
behavior of the function call operator to a notional temporary,
or the function call operator for such closure classes could be
made static.</P>

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

<OL><LI><P>Change 7.5.5.1 [expr.prim.lambda.closure] paragraph 7 as follows,
splitting it into two paragraphs:</P></LI>

<BLOCKQUOTE>

<P>...The value returned by this conversion function is the
address of a function <TT>F</TT> that, when invoked, has the
same effect as invoking the closure type's function call
operator <SPAN style="font-weight:bold;background-color:#A0FFA0">on a default-constructed instance of the
closure type</SPAN>. <TT>F</TT> is a constexpr function if
the function call operator is a constexpr function.</P>

<P>For a generic lambda with
no <I>lambda-capture</I>, the closure type has...</P>

</BLOCKQUOTE>

<LI><P>Change 7.5.5.1 [expr.prim.lambda.closure] paragraph 9 as follows:</P></LI>

<BLOCKQUOTE>

The value returned by any given specialization of this
conversion function template is the address of a function <TT>F</TT>
that, when invoked, has the same effect as invoking the
generic lambda's corresponding function call operator
template specialization <SPAN style="font-weight:bold;background-color:#A0FFA0">on a default-constructed instance
of the closure type</SPAN>. <TT>F</TT>
is a constexpr function if the
corresponding specialization is a constexpr
function <SPAN style="font-weight:bold;background-color:#A0FFA0">and is an immediate function if the function
call operator template specialization is an immediate
function</SPAN>. [<I>Note:</I> This will result...

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="1938"></A><H4>1938.
  
Should hosted/freestanding be implementation-defined?
</H4><B>Section: </B>4.1&#160; [intro.compliance]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2014-06-09


<P>Whether an implementation is hosted or freestanding is only
required to be documented by the value of
the <TT>__STDC_HOSTED__</TT> macro
(14.8 [cpp.predefined]). Should this characteristic be
classified as implementation-defined, thus requiring
documentation?</P>

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

<P>Change 15.5.1.3 [compliance] paragraph 1 as follows:</P>

<BLOCKQUOTE>

Two kinds of implementations are defined: <I>hosted</I>
and <I>freestanding</I> (4.1 [intro.compliance]) <SPAN style="font-weight:bold;background-color:#A0FFA0">the
kind of the implementation is
implementation-defined</SPAN>. For a hosted implementation,
this document describes the set of available headers.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2020"></A><H4>2020.
  
Inadequate description of odr-use of implicitly-invoked functions
</H4><B>Section: </B>6.2&#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>2014-10-08


<P>According to 6.2 [basic.def.odr] paragraph 3,</P>

<BLOCKQUOTE>

A function whose name appears as a potentially-evaluated
expression is odr-used if it is the unique lookup result or
the selected member of a set of overloaded functions
(6.4 [basic.lookup], 11.3 [over.match],
11.4 [over.over]), unless it is a pure virtual
function and its name is not explicitly
qualified. [<I>Note:</I> This covers calls to named
functions (7.6.1.2 [expr.call]), operator overloading
(Clause 11 [over]), user-defined conversions
(10.3.7.2 [class.conv.fct]), allocation function for
placement new (7.6.2.4 [expr.new]), as well as
non-default initialization (9.3 [dcl.init]). A
constructor selected to copy or move an object of class type
is odr-used even if the call is actually elided by the
implementation (_N4750_.15.8 [class.copy]). &#8212;<I>end
note</I>] An allocation or deallocation function for a class
is odr-used by a new expression appearing in a
potentially-evaluated expression as specified in
7.6.2.4 [expr.new] and 10.11 [class.free]. A
deallocation function for a class is odr-used by a delete
expression appearing in a potentially-evaluated expression
as specified in 7.6.2.5 [expr.delete] and
10.11 [class.free].

</BLOCKQUOTE>

<P>There are a couple of problems with this specification.  First,
contrary to the note, the names of overloaded operators, conversion
functions, etc., do not appear in potentially-evaluated expressions,
so the normative text does not make the note true.  Also, the
&#8220;as specified in&#8221; references do not cover odr-use
explicitly, only the invocation of the functions.</P>

<P>One possible way of addressing these deficiencies would be a
blanket rule like,</P>

<BLOCKQUOTE>

A function is odr-used if it is invoked by a potentially-evaluated
expression.

</BLOCKQUOTE>

<P>(The existing wording about appearing in a potentially-evaluated
expression would still be needed for non-call references.)</P>

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

<OL><LI><P>Change 6.2 [basic.def.odr] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

An expression <SPAN style="font-weight:bold;background-color:#A0FFA0">or conversion</SPAN>
is <I>potentially evaluated</I> unless it is
an unevaluated operand (7.2 [expr.prop])<SPAN style="font-weight:bold;background-color:#A0FFA0">,</SPAN>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">or</SPAN> a subexpression thereof<SPAN style="font-weight:bold;background-color:#A0FFA0">, or a conversion in
an initialization or conversion sequence in such a
context</SPAN>.  The set of <I>potential results</I> of an
expression <TT>e</TT> is defined as follows:...

</BLOCKQUOTE>

<LI><P>Cbange 6.2 [basic.def.odr] paragraph 3 as follows:</P></LI>

<BLOCKQUOTE>

<P>A function is <I>named by an expression</I> as follows:</P>

<UL><LI><P>A function <SPAN style="text-decoration:line-through;background-color:#FFA0A0">whose name appears in an
expression</SPAN> is named by <SPAN style="text-decoration:line-through;background-color:#FFA0A0">that</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">an</SPAN>
expression <SPAN style="font-weight:bold;background-color:#A0FFA0">or conversion</SPAN> if it is the unique
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">lookup</SPAN> result <SPAN style="font-weight:bold;background-color:#A0FFA0">of a name lookup</SPAN> or the
selected member of a set of overloaded functions
(6.4 [basic.lookup], 11.3 [over.match],
11.4 [over.over]) <SPAN style="font-weight:bold;background-color:#A0FFA0">in an overload resolution
performed as part of forming that expression or
conversion</SPAN>, unless it is a pure virtual function and
either <SPAN style="text-decoration:line-through;background-color:#FFA0A0">its name is not</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">the expression is not an <I>id-expression</I> naming
the function with an</SPAN>explicitly
qualified <SPAN style="font-weight:bold;background-color:#A0FFA0">name</SPAN> or the expression forms a pointer
to member (7.6.2.1 [expr.unary.op]). [<I>Note:</I> This
covers taking the address of functions
(7.3.3 [conv.func], 7.6.2.1 [expr.unary.op]),
calls to named functions (7.6.1.2 [expr.call]),
operator overloading (Clause 11 [over]),
user-defined conversions (10.3.7.2 [class.conv.fct]),
allocation functions for <SPAN style="text-decoration:line-through;background-color:#FFA0A0">placement</SPAN>
<I>new-expression</I>s (7.6.2.4 [expr.new]), as
well as non-default initialization
(9.3 [dcl.init]). A constructor selected to copy
or move an object of class type is considered to be named by
an expression <SPAN style="font-weight:bold;background-color:#A0FFA0">or conversion</SPAN> even if the call is
actually elided by the implementation
(10.9.5 [class.copy.elision]). &#8212;<I>end
note</I>]</P></LI>

<LI><P>A<SPAN style="text-decoration:line-through;background-color:#FFA0A0">n allocation or</SPAN> deallocation function for
a class is named by a <I>new-expression</I> <SPAN style="font-weight:bold;background-color:#A0FFA0">if it is
the single matching deallocation function for the allocation
function selected by o verload resolution,</SPAN> as
specified in 7.6.2.4 [expr.new] and
10.11 [class.free].</P></LI>

<LI><P>A deallocation function for a class is named by a <SPAN style="text-decoration:line-through;background-color:#FFA0A0">delete
expression</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><I>delete-expression</I> if it is the selected usual
deallocation function</SPAN> as specified in
7.6.2.5 [expr.delete] and
10.11 [class.free].</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 6.2 [basic.def.odr] paragraph 7 as follows:</P></LI>

<BLOCKQUOTE>

A virtual member function is odr-used if it is not pure. A
function is odr-used if it is named by a
potentially-evaluated expression <SPAN style="font-weight:bold;background-color:#A0FFA0">or conversion</SPAN>. A
non-placement...

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2051"></A><H4>2051.
  
Simplifying alias rules
</H4><B>Section: </B>7.2.1&#160; [basic.lval]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2014-12-03




<P>The aliasing rules of 7.2.1 [basic.lval] paragraph 10 were
adapted from C with additions for C++.  However, a number of the points
either do not apply or are subsumed by other points.  For example, the
provision for aggregate and union types is needed in C for struct
assignment, which in C++ is done via constructors and assignment
operators in C++, not by accessing the complete object.</P>

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

<P>Replace 7.2.1 [basic.lval] paragraph 10 as follows:</P>

<P>If a program attempts to access the stored value of an object
through a glvalue whose type is not similar (7.3.5 [conv.qual])
to one of the following types the behavior is undefined:
[<I>Footnote:</I>... &#8212;<I>end footnote</I>]</P>

<UL><LI><P>the dynamic type of the object,</P></LI>

<LI><P>the signed or unsigned type corresponding to the dynamic
type of the object, or</P></LI>

<LI><P>a <TT>char</TT> or <TT>unsigned char</TT> type.</P></LI>

</UL>

<P><B>Additional note, October, 2015:</B></P>

<P>It has been suggested 
that the aliasing rules should be extended to permit an object of
an enumeration with a fixed underlying type to alias an object with
that underlying type.</P>

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

<OL><LI><P>Change 7.2.1 [basic.lval] paragraph 11 as follows:</P></LI>

<BLOCKQUOTE>

<P>If a program attempts to access the stored value of an
object through a glvalue <SPAN style="text-decoration:line-through;background-color:#FFA0A0">of other than</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">whose type is not similar (7.3.5 [conv.qual])
to</SPAN> one of the following types the behavior is
undefined:<SUP>58</SUP></P>

<UL><LI><P>the dynamic type of the object,</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">a cv-qualified version of the dynamic type of the object,</SPAN>
</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">a type similar (as defined in 7.3.5 [conv.qual]) to
the dynamic type of the object,</SPAN></P></LI>

<LI><P>a type that is the signed or unsigned type
corresponding to the dynamic type of the object,</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">a type that is the signed or unsigned type
corresponding to a cv-qualified version of the dynamic type
of the object,</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">an aggregate or union type that includes one of the
aforementioned types among its elements or non-static data
members (including, recursively, an element or non-static
data member of a subaggregate or contained union),</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">a type that is a (possibly cv-qualified) base class type of
the dynamic type of the object,</SPAN></P></LI>

<LI><P>a <TT>char</TT>, <TT>unsigned char</TT>, or
<TT>std::byte</TT> type.</P></LI>

</UL>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">If a program invokes a defaulted copy/move constructor
or copy/move assignment operator for a union of type <TT>U</TT>
with a glvalue argument that does not denote an object of type
<I>cv</I> <TT>U</TT> within its lifetime, the behavior is
undefined. [<I>Note:</I> Unlike in C, C++ has no accesses of
class type. &#8212;<I>end note</I>]</SPAN></P>

</BLOCKQUOTE>

<LI><P>Change 7.3.5 [conv.qual] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

<P>A <I>cv-decomposition</I> of a type <TT>T</TT>
is a sequence of <I>cv<SUB>i</SUB></I>
and <I>P<SUB>i</SUB></I> such that <TT>T</TT> is</P>

<UL>&#8220;<I>cv<SUB>0</SUB> P<SUB>0</SUB> &#183;&#183;&#183; cv<SUB>n-1</SUB> P<SUB>n-1</SUB> cv<SUB>n</SUB></I> <TT>U</TT>&#8221; for <I>n</I> <SPAN style="text-decoration:line-through;background-color:#FFA0A0">&gt;</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">&#8805;</SPAN> 0,</UL>

<P>where...</P>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2083"></A><H4>2083.
  
Incorrect cases of odr-use
</H4><B>Section: </B>6.2&#160; [basic.def.odr]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Hubert Tong
 &#160;&#160;&#160;

 <B>Date: </B>2015-02-11




<P>The resolution of issue 1741 was not
intended to cause odr-use to occur in cases where it did not do so
previously.  However, in an example like</P>

<PRE>
  extern int globx;
  int main() {
    const int &amp;x = globx;
    struct A {
     const int *foo() {
       return &amp;x;
     }
    } a;
    return *a.foo();
  }
</PRE>

<P><TT>x</TT> satisfies the requirements for appearing in a
constant expression, but applying the lvalue-to-rvalue
converstion to <TT>x</TT> does not yield a constant expression.
Similarly,</P>

<PRE>
  struct A {
    int q;
    constexpr A(int q) : q(q) { }
    constexpr A(const A &amp;a) : q(a.q * 2) { }
  };

  int main(void) {
    constexpr A a(42);
    constexpr int aq = a.q;
    struct Q {
     int foo() { return a.q; }
    } q;
    return q.foo();
  }
</PRE>

<P><TT>a</TT> satisfies the requirements for appearing in a constant
expression, but applying the lvalue-to-rvalue conversion to <TT>a</TT>
invokes a non-trivial function.</P>

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

<OL><LI><P>Change 6.2 [basic.def.odr] bullet 2.4 as follows:</P></LI>

<BLOCKQUOTE>

<P>An expression is <I>potentially evaluated</I> unless it
is an unevaluated operand (7.2 [expr.prop]) or a
subexpression thereof.  The set of <I>potential results</I>
of an expression <TT>e</TT> is defined as follows:</P>

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

<LI><P>If <TT>e</TT> is a pointer-to-member expression
(7.6.4 [expr.mptr.oper]) <SPAN style="text-decoration:line-through;background-color:#FFA0A0">whose second operand is a
constant expression</SPAN>, the set contains the potential results
of the object expression.</P></LI>

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

<LI><P>Otherwise, the set is empty.</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 6.2 [basic.def.odr] paragraph 4, converting the
running text into bullets, as follows:</P></LI>

<BLOCKQUOTE>

<P>A variable <TT>x</TT> whose name appears as a
potentially-evaluated expression <TT>e<SPAN style="text-decoration:line-through;background-color:#FFA0A0">x</SPAN></TT> is odr-used
by <TT>e<SPAN style="text-decoration:line-through;background-color:#FFA0A0">x</SPAN></TT> unless <SPAN style="text-decoration:line-through;background-color:#FFA0A0">applying the lvalue-to-rvalue
conversion (7.3.1 [conv.lval]) to <TT>x</TT> yields
a constant expression (7.7 [expr.const]) that does
not invoke a function other than a trivial special member
function (10.3.3 [special]) and, if <TT>x</TT> is
an object,</SPAN></P>

<UL><LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>x</TT> is a reference that is usable in
constant expressions (7.7 [expr.const]), or</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>x</TT> is a variable of non-reference type
that is usable in constant expressions and has no mutable
subobjects, and</SPAN> <TT>e<SPAN style="text-decoration:line-through;background-color:#FFA0A0">x</SPAN></TT> is an element
of the set of potential results of an
expression <SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>e</TT>, where either</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">of
non-volatile-qualified non-class type to which</SPAN> the
lvalue-to-rvalue conversion (7.3.1 [conv.lval]) is
applied <SPAN style="text-decoration:line-through;background-color:#FFA0A0">to <TT>e</TT></SPAN>, or <SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>e</TT> is</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>x</TT> is a variable of non-reference type, and
<TT>e</TT> is an element of the set of potential results of</SPAN>
a discarded-value expression (7.2 [expr.prop])
<SPAN style="font-weight:bold;background-color:#A0FFA0">to which the lvalue-to-rvalue conversion is not
applied.</SPAN></P></LI>

</UL>

</BLOCKQUOTE>

<P>This resolution also resolves issues 2103
and 2170.</P>

</OL>

<BR><BR><HR><A NAME="2103"></A><H4>2103.
  
Lvalue-to-rvalue conversion is irrelevant in odr-use of a reference
</H4><B>Section: </B>6.2&#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>2015-03-17




<P>Issue 1741 accidentally caused
6.2 [basic.def.odr] to indicate that an lvalue-to-rvalue
conversion is necessary for the odr-use of a reference.  This
is incorrect; any appearance of the reference name in a
potentially-evaluated expression should require the reference
to be defined.</P>

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

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

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

<BR><BR><HR><A NAME="2170"></A><H4>2170.
  
Unclear definition of odr-use for arrays
</H4><B>Section: </B>6.2&#160; [basic.def.odr]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Hubert Tong
 &#160;&#160;&#160;

 <B>Date: </B>2015-09-02




<P>The current definition of odr-use of a variable is problematic
when applied to an array:</P>

<BLOCKQUOTE>

A variable <TT>x</TT> whose name appears as a
potentially-evaluated expression <TT>ex</TT> is odr-used
by <TT>ex</TT> unless applying the lvalue-to-rvalue
conversion (7.3.1 [conv.lval]) to <TT>x</TT> yields a
constant expression (7.7 [expr.const]) that does
not invoke any non-trivial functions and, if <TT>x</TT> is
an object, <TT>ex</TT> is an element of the set of potential
results of an expression <TT>e</TT>, where either the
lvalue-to-rvalue conversion (7.3.1 [conv.lval]) is
applied to <TT>e</TT>, or <TT>e</TT> is a discarded-value
expression (Clause 7 [expr]).

</BLOCKQUOTE>

<P>Consider an example like</P>

<PRE>
  struct S {
    constexpr static const int arr[3] = { 0, 1, 2 };
  };
  int i = S::arr[1];  //<SPAN style="font-family:Times;font-style:italic"> Should not require </SPAN>S::arr<SPAN style="font-family:Times;font-style:italic"> to be defined</SPAN>
</PRE>

<P>Although the &#8220;set of potential results&#8221; test
correctly handles the subscripting operation (since the
resolution of issue 1926), it
requires applying the lvalue-to-rvalue conversion to
<TT>S::arr</TT> itself and not just to the result of the
subscripting operation.  Class objects exhibit a similar
problem.</P>

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

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

<BR><BR><HR><A NAME="2257"></A><H4>2257.
  
Lifetime extension of references vs exceptions
</H4><B>Section: </B>6.6.6&#160; [class.temporary]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Hubert Tong
 &#160;&#160;&#160;

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




<P>There is implementation divergence on the following example:</P>

<PRE>
  #include &lt;stdio.h&gt; 
  struct A { 
    bool live; 
    A() : live(true) { 
      static int cnt; 
      if (cnt++ == 1) throw 0; 
    } 
    ~A() { 
      fprintf(stderr, "live: %d\n", live); 
      live = false; 
    } 
  }; 
  struct AA { A &amp;&amp;a0, &amp;&amp;a1; }; 
  void doit() { 
    static AA aa = { A(), A() }; 
  } 
  int main(void) { 
    try { 
      doit(); 
    } 
    catch (...) { 
      fprintf(stderr, "in catch\n"); 
      doit(); 
    } 
  }
</PRE>

<P>Some implementations produce</P>

<PRE>
  in catch
  live: 1
  live: 1
  live: 0
</PRE>

<P>While others produce</P>

<PRE>
  live: 1
  in catch
  live: 1
  live: 1
</PRE>

<P>With regard to the reference to which the
first-constructed object of type <TT>A</TT> is bound, at
what point should its lifetime end? Perhaps it should be
specified that the lifetime of the temporary is only
extended if said initialization does not exit via an
exception (which means that calling <TT>::std::exit(0)</TT>
as opposed to throwing would not result in a call to
<TT>~A()</TT>). </P>

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

<P><B>Notes from the December, 2016 teleconference:</B></P>

<P>The consensus was that the temporaries should be destroyed immediately
if an exception occurs. 13.2 [except.ctor] paragraph 3 should
be extended to apply to static initialization, so that even if a temporary
is lifetime-extended (because it has static storage duration), it will be
destroyed in case of an exception.</P>

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

<P>Change 13.2 [except.ctor] paragraph 3 as follows:</P>

<BLOCKQUOTE>

If the initialization or destruction of an object other than
by delegating constructor is terminated by an exception, the
destructor is invoked for each of the object's direct
subobjects and, for a complete object, virtual base class
subobjects, whose initialization has completed
(9.3 [dcl.init]) and whose destructor has not yet
begun execution, except that in the case of destruction, the
variant members of a union-like class are not destroyed.
<SPAN style="font-weight:bold;background-color:#A0FFA0">[<I>Note:</I> If such an object has a reference member
that extends the lifetime of a temporary object, this ends
the lifetime of the reference member, so the lifetime of the
temporary object is effectively not extended.&#8212;<I>end
note</I>]</SPAN> The subobjects are destroyed in the reverse
order of the completion of their construction. Such
destruction is sequenced before entering a handler of
the <I>function-try-block</I> of the constructor or
destructor, if any.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2266"></A><H4>2266.
  
Has dependent type vs is type-dependent
</H4><B>Section: </B>12.7.2.1&#160; [temp.dep.type]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Fedor Sergeev
 &#160;&#160;&#160;

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




<P>According to 12.7.2.1 [temp.dep.type] bullet 6.3.2, one criterion
for a name being a member of an unknown specialization is if the name is
an <I>id-expression</I> denoting the member in a member access expression
and</P>

<BLOCKQUOTE>

the type of the object expression is dependent and is not the current
instantiation.

</BLOCKQUOTE>

<P>This should presumably say that the object expression is type-dependent
and not that it has a dependent type; &#8220;has a dependent type&#8221;
should be applied only to declarations, not expressions.</P>

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

<P>Change 12.7.2.1 [temp.dep.type] bullet 6.3.2 as follows:</P>

<BLOCKQUOTE>

<P>A name is a <I>member of an unknown specialization</I>
if it is</P>

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

<LI><P>An <I>id-expression</I> denoting the member in a class
member access expression (7.6.1.5 [expr.ref]) in
which either</P></LI>

<UL><LI><P>the type of the object expression is the current
instantiation, the current instantiation has at least one
dependent base class, and name lookup of
the <I>id-expression</I> does not find a member of a class
that is the current instantiation or a non-dependent base
class thereof; or</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">the type of</SPAN>
the object expression is <SPAN style="font-weight:bold;background-color:#A0FFA0">type-</SPAN>dependent and is not
the current instantiation.</P></LI>

</UL>

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2289"></A><H4>2289.
  
Uniqueness of structured binding names
</H4><B>Section: </B>6.3.1&#160; [basic.scope.declarative]
 &#160;&#160;&#160;

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

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

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




<P>The current wording is not clear regarding examples like
the following:</P>

<PRE>
  struct A { int x; } a; 
  struct B {} b; template&lt;int&gt; int &amp;get(const B&amp;); 
  struct C {}; int c[1]; 
  auto [A] = a; //<SPAN style="font-family:Times;font-style:italic"> ok? </SPAN>
  auto [B] = b; //<SPAN style="font-family:Times;font-style:italic"> ok? </SPAN>
  auto [C] = c; //<SPAN style="font-family:Times;font-style:italic"> ok? </SPAN>
</PRE>

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

<P>Structured bindings have no C compatibility implications, so the
tag/nontag treatment need not apply.</P>

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

<P>Change 6.3.1 [basic.scope.declarative] paragraph 4 as follows:</P>

<BLOCKQUOTE>

<P>Given a set of declarations in a single declarative region,
each of which specifies the same unqualified name,</P>

<UL><LI><P>they shall all refer to the same entity, or all refer to
functions and function templates; or</P></LI>

<LI><P>exactly one declaration shall declare a class name or
enumeration name that is not a typedef name and the other
declarations shall all refer to the same variable,
non-static data member, or enumerator, or all refer to
functions and function templates; in this case the class
name or enumeration name is hidden
(6.3.10 [basic.scope.hiding]). [<I>Note:</I>
A <SPAN style="font-weight:bold;background-color:#A0FFA0">structured binding (9.5 [dcl.struct.bind]),</SPAN>
namespace name <SPAN style="font-weight:bold;background-color:#A0FFA0">(9.7 [basic.namespace]),</SPAN>
or <SPAN style="text-decoration:line-through;background-color:#FFA0A0">a</SPAN> class template
name <SPAN style="font-weight:bold;background-color:#A0FFA0">(Clause 12 [temp])</SPAN> must be
unique in its declarative
region <SPAN style="text-decoration:line-through;background-color:#FFA0A0">(9.7.2 [namespace.alias],
Clause 12 [temp])</SPAN>. &#8212;<I>end
note</I>]</P></LI>

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2353"></A><H4>2353.
  
Potential results of a member access expression for a static data member
</H4><B>Section: </B>6.2&#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>2017-08-18


<P>According to 6.2 [basic.def.odr] bullet 2.3, the potential
results of a member access expression are simply the object expression.
This rule incorrectly handles an example like:</P>

<PRE>
  struct X {
    static const int n = 0;
  };
  X x = {};

  int b = x.n;
</PRE>

<P>Because <TT>X::n</TT> is not one of the potential results, the
expression <TT>x.n</TT> odr-uses <TT>X::n</TT>, requiring it to be
defined.</P>

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

<P>CWG agreed with the suggested direction to make the member a
potential result in cases like the example.</P>

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

<P>Change 6.2 [basic.def.odr] paragraph 2 as follows:</P>

<BLOCKQUOTE>

<P>An expression is potentially evaluated unless it is an
unevaluated operand (7.2 [expr.prop]) or a
subexpression thereof.  The set of potential results of an
expression <TT>e</TT> is defined as follows:</P>

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

<LI><P>If <TT>e</TT> is a class member access expression
(7.6.1.5 [expr.ref]) <SPAN style="font-weight:bold;background-color:#A0FFA0">of the form
<TT>e1 . template</TT><SUB><I>opt</I></SUB><TT> e2</TT>
naming a non-static data member</SPAN>, the set contains the
potential results of <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the object expression</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>e1</TT></SPAN>.</P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">if <TT>e</TT> is a class member access expression
naming a static data member, the set contains the
<I>id-expression</I> designating the data member.</SPAN></P></LI>

<LI><P>If <TT>e</TT> is a pointer-to-member expression
(7.6.4 [expr.mptr.oper]) <SPAN style="text-decoration:line-through;background-color:#FFA0A0">whose second operand is a
constant expression</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">of the form
<TT>e1 .* e2</TT></SPAN>, the set contains the potential results
of <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the object expression</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>e1</TT></SPAN>.</P></LI>

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

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2354"></A><H4>2354.
  
Extended alignment and object representation
</H4><B>Section: </B>6.6.5&#160; [basic.align]
 &#160;&#160;&#160;

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

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

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


<P>There is implementation variance in the treatment of an example like:</P>

<PRE>
  enum struct alignas(64) A {};
  A a[10]; 
</PRE>

<P>The Standard does not appear to indicate whether padding bits are added
to the object representation for an enumeration or not, affecting the
result of <TT>sizeof</TT> and the alignment of the array elements.</P>

<P>If the extended alignment does not affect the object representation of
the type, it would be useful to specify that the array declaration is
ill-formed because it requires violating the alignment requirement (and
similarly for an array <I>new-expression</I> where the bound is known at
compile time).</P>

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

<P>It appears that the same question exists for class types that are
directly given extended alignment, as opposed to receiving it from a
subobject.</P>

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

<P>CWG agreed to remove permission for <TT>alignas</TT> to
be applied to enumerations. The class case is already
handled by the wording in 7.6.2.3 [expr.sizeof]
paragraph 2 that the size of a class &#8220;includes any padding
required for placing objects of that type in an array.&#8221;</P>

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

<P>Change 9.11.2 [dcl.align] paragraph 1 as follows:</P>

<BLOCKQUOTE>

An <I>alignment-specifier</I> may be applied to a variable
or to a class data member, but it shall not be applied to a
bit-field, a function parameter, or
an <I>exception-declaration</I>
(13.3 [except.handle]). An <I>alignment-specifier</I>
may also be applied to the declaration of a class (in
an <I>elaborated-type-specifier</I>
(9.1.7.3 [dcl.type.elab]) or <I>class-head</I> (Clause
10 [class]), respectively)<SPAN style="text-decoration:line-through;background-color:#FFA0A0"> and to
the declaration of an enumeration (in
an <I>opaque-enum-declaration</I> or <I>enum-head</I>,
respectively (9.6 [dcl.enum]))</SPAN>.
An <I>alignment-specifier</I> with an ellipsis...

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2365"></A><H4>2365.
  
Confusing specification for <TT>dynamic_cast</TT>
</H4><B>Section: </B>7.6.1.7&#160; [expr.dynamic.cast]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Shiyao Ma
 &#160;&#160;&#160;

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


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

<P>According to 7.6.1.7 [expr.dynamic.cast] paragraph 4,</P>

<BLOCKQUOTE>

If the value of <TT>v</TT>
is a null pointer value in the pointer case, the result
is the null pointer value of type <TT>T</TT>.

</BLOCKQUOTE>

<P>Paragraph 5 deals with the case of a simple up-cast, where no runtime
type identification is required. Paragraph 6 says,</P>

<BLOCKQUOTE>

Otherwise, <TT>v</TT> shall be a pointer to or a glvalue of a polymorphic
type (10.6.2 [class.virtual]).

</BLOCKQUOTE>

<P>This organization of the material makes it sound as if the requirement
for polymorphic class types does not apply if the argument is a null
pointer value, which, of course, cannot be determined at compile time. The
intent is that a null pointer value argument produces a null pointer value
result, regardless of whether the relationship between the classes requires
runtime type identification or not, but that the requirement for
polymorphic classes applies for all casts that are not simple up-casts. The
wording should be clarified.</P>

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

<P>Change 7.6.1.7 [expr.dynamic.cast] paragraphs 4-6 as follows:</P>

<BLOCKQUOTE>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">If the value of <TT>v</TT>
is a null pointer value in the pointer
case, the result is the null pointer value of type <TT>T</TT>.</SPAN>
</P>

<P>If <TT>T</TT>
is &#8220;pointer to <I>cv1</I> <TT>B</TT>&#8221; and <TT>v</TT>
has type &#8220;pointer to <I>cv2</I>
<TT>D</TT>&#8221; such that <TT>B</TT> is a base class
of <TT>D</TT>, the result is a pointer to the
unique <TT>B</TT> subobject of the <TT>D</TT> object pointed
to by <TT>v</TT><SPAN style="font-weight:bold;background-color:#A0FFA0">, or a null pointer value if <TT>v</TT>
is a null pointer value</SPAN>. Similarly, if <TT>T</TT> is...</P>

<P>Otherwise, <TT>v</TT>
shall be a pointer to or a glvalue of a
polymorphic type (10.6.2 [class.virtual]).</P>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">If <TT>v</TT> is a null pointer value, the result is a
null pointer value.</SPAN></P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2368"></A><H4>2368.
  
Differences in relational and three-way constant comparisons
</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>2017-11-11




<P>According to 7.7 [expr.const] bullets 2.21 and
2.22, the characteristics of three-way and relational
comparisons that disqualify them as constant expressions are
different:</P>

<UL><LI><P>a three-way comparison
(7.6.8 [expr.spaceship]) comparing pointers that do not
point to the same complete object or to any subobject
thereof;</P></LI>

<LI><P>a relational (7.6.9 [expr.rel]) or equality
(7.6.10 [expr.eq]) operator where the result is
unspecified;</P></LI>

</UL>

<P>These are <I>not</I> equivalent, with odd results:</P>

<PRE>
  struct A { 
    int a; 
  private: 
    int b; 
    constexpr auto f() { return &amp;a &lt; &amp;b; }   //<SPAN style="font-family:Times;font-style:italic"> not constant </SPAN>
    constexpr auto g() { return &amp;a &lt;=&gt; &amp;b; } //<SPAN style="font-family:Times;font-style:italic"> returns unspecified value </SPAN>
  }; 
</PRE>

<P>Similarly,</P>

<PRE>
  struct B { int n; }; 
  struct C : B { int m; } c; 
  constexpr auto x = &amp;c.n &lt; &amp;c.m;   //<SPAN style="font-family:Times;font-style:italic"> not constant </SPAN>
  constexpr auto y = &amp;c.n &lt;=&gt; &amp;c.m; //<SPAN style="font-family:Times;font-style:italic"> returns unspecified value </SPAN>
</PRE>

<P>The three-way rule seems to be the correct one, but
additional wording is needed in 7.6.9 [expr.rel] to
specify the relational ordering within a single object:
addresses of subobjects of the same complete object should
be weakly ordered, and when restricted to subobjects that
are not permitted to have the same address, should be
totally ordered.</P>

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

<P>The consensus of CWG was to make the 3-way operator cases
non-constant, as the relational cases are.</P>

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

<P>Change 7.7 [expr.const] bullets 2.22 and 2.23 as follows,
merging tbe bullets:</P>

<BLOCKQUOTE>

<P>An expression <TT>e</TT> is a <I>core constant
expression</I> unless the evaluation of <TT>e</TT>,
following the rules of the abstract machine
(6.8.1 [intro.execution]), would evaluate one of the
following expressions:</P>

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

<LI><P>a three-way comparison (7.6.8 [expr.spaceship])<SPAN style="font-weight:bold;background-color:#A0FFA0">,</SPAN>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">comparing pointers that do not point to the same complete
object or to any subobject thereof;</SPAN>
</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">a</SPAN> relational
(7.6.9 [expr.rel])<SPAN style="font-weight:bold;background-color:#A0FFA0">,</SPAN> or equality
(7.6.10 [expr.eq]) operator where the result is
unspecified;</P></LI>

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

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2372"></A><H4>2372.
  
Incorrect matching rules for block-scope <TT>extern</TT> declarations
</H4><B>Section: </B>6.5&#160; [basic.link]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Chen Fuxingi
 &#160;&#160;&#160;

 <B>Date: </B>2017-12-17


<P>According to 6.5 [basic.link] paragraph 6,</P>

<BLOCKQUOTE>

The name of a function declared in block scope and the name
of a variable declared by a block scope <TT>extern</TT>
declaration have linkage. If there is a visible declaration
of an entity with linkage having the same name and type,
ignoring entities declared outside the innermost enclosing
namespace scope, the block scope declaration declares that
same entity and receives the linkage of the previous
declaration. If there is more than one such matching entity,
the program is ill-formed. Otherwise, if no matching entity
is found, the block scope entity receives external linkage.

</BLOCKQUOTE>

<P>The requirement that the entities have the same type does
not cover all cases that it should. Consider an example like:</P>

<PRE>
  static int a[3];
  void g() {
    printf("%p\n", (void*)a);
    extern int a[];
    printf("%p\n", (void*)a);
  }
</PRE>

<P>According to the cited wording, the block-scope declaration of
<TT>a</TT> does not match the namespace scope declaration because
<TT>int[]</TT> and <TT>int[3]</TT> are different types, thus the
first reference to <TT>a</TT> refers to the static variable while
the second one refers to a variable <TT>a</TT> defined in some
other translation unit. This is clearly not intended, and current
implementations treat both references as referring to the static
variable.</P>

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

<P>CWG agreed with the direction and noted that a similar situation
occurs with <TT>extern "C"</TT> functions.</P>

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

<P>Change 6.5 [basic.link] paragraph 6 as follows:</P>

<BLOCKQUOTE>

<P>The name of a function declared in block scope and the
name of a variable declared by a block scope <TT>extern</TT>
declaration have linkage. If there is a visible declaration
of an entity with linkage<SPAN style="text-decoration:line-through;background-color:#FFA0A0"> having the same name and
type</SPAN>, ignoring entities declared outside the innermost
enclosing namespace scope, <SPAN style="font-weight:bold;background-color:#A0FFA0">such that the block scope
declaration would be a (possibly ill-formed) redeclaration
if the two declarations appeared in the same declarative
region,</SPAN> the block scope declaration declares that same
entity and receives the linkage of the previous
declaration. If there is more than one such matching entity,
the program is ill-formed. Otherwise, if no matching entity
is found, the block scope entity receives external
linkage. If, within a translation unit, the same entity is
declared with both internal and external linkage, the
program is ill-formed. [<I>Example:</I></P>

<PRE>
  static void f();
<SPAN style="font-weight:bold;background-color:#A0FFA0">  extern "C" void h();</SPAN>
  static int i = 0;      //<SPAN style="font-family:Times;font-style:italic"> #1</SPAN>
  void g() {
    extern void f();     //<SPAN style="font-family:Times;font-style:italic"> internal linkage</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">    extern void h();     //<SPAN style="font-family:Times;font-style:italic"> </SPAN>C<SPAN style="font-family:Times;font-style:italic"> language linkage</SPAN>
</SPAN>
    int i;               //<SPAN style="font-family:Times;font-style:italic"> #2: <TT>i</TT> has no linkage</SPAN>
    {
      extern void f();   //<SPAN style="font-family:Times;font-style:italic"> internal linkage</SPAN>
      extern int i;      //<SPAN style="font-family:Times;font-style:italic"> #3: external linkage, ill-formed</SPAN>
    }
  }
</PRE>

<P>Without the declaration at line #2, the declaration at
line #3 would link with the declaration at line #1.  Because
the declaration with internal linkage is hidden, however, #3
is given external linkage, making the program
ill-formed. &#8212;<I>end example</I>]</P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2379"></A><H4>2379.
  
Missing prohibition against <TT>constexpr</TT> in <TT>friend</TT> declaration
</H4><B>Section: </B>12.6.4&#160; [temp.friend]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2018-06-14


<P>According to 12.6.4 [temp.friend] paragraph 8,</P>

<BLOCKQUOTE>

When a friend declaration refers to a specialization of a function
template, the function parameter declarations shall not include default
arguments, nor shall the inline specifier be used in such a declaration.

</BLOCKQUOTE>

<P>Presumably this should also include the <TT>constexpr</TT>
specifier.</P>

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

<P>This should also cover the newly-added <TT>consteval</TT>
specifier.</P>

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

<P>Change 12.6.4 [temp.friend] paragraph 8 as follows:</P>

<BLOCKQUOTE>

When a friend declaration refers to a specialization of a
function template, the function parameter declarations shall
not include default arguments, nor shall the <SPAN style="text-decoration:line-through;background-color:#FFA0A0">inline
specifier</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>inline</TT>, <TT>constexpr</TT>,
or <TT>consteval</TT> specifiers</SPAN> be used in such a
declaration.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2380"></A><H4>2380.
  
<I>capture-default</I> makes too many references odr-usable
</H4><B>Section: </B>6.2&#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>2018-06-14


<P>The current rule for determining when a local entity is odr-usable
because of a <I>capture-default</I> is too broad. For example:</P>

<PRE>
  void f() {
    int n;
    void g(int k = n);                  //<SPAN style="font-family:Times;font-style:italic"> ill-formed</SPAN>
    [](int k = n) {};                   //<SPAN style="font-family:Times;font-style:italic"> ill-formed</SPAN>
    [=](int k = n) {};                  //<SPAN style="font-family:Times;font-style:italic"> valid!</SPAN>
    [=](int k = [=]{ return n; }()) {}; //<SPAN style="font-family:Times;font-style:italic"> valid!</SPAN>
  }
</PRE>

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

<P>Change 6.2 [basic.def.odr] bullet 9.2.2 and add to the
example as follows:</P>

<BLOCKQUOTE>

<P>A local entity (Clause 6.2 [basic.def.odr])
is <I>odr-usable</I> in a declarative region
(6.3.1 [basic.scope.declarative]) if:</P>

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

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

<LI><P>the intervening declarative region is the function parameter
scope of a <I>lambda-expression</I> that has
a <I>simple-capture</I> naming the entity or has
a <I>capture-default</I><SPAN style="font-weight:bold;background-color:#A0FFA0">, and the block scope of the
<I>lambda-expression</I> is also an intervening declarative
region</SPAN>.</P></LI>

</UL>

</UL>

<P>If a local entity is odr-used in a declarative region in
which it is not odr-usable, the program is ill-formed.
[<I>Example:</I></P>

<PRE>
  void f(int n) {
    [] { n = 1; };        //<SPAN style="font-family:Times;font-style:italic"> error, </SPAN>n<SPAN style="font-family:Times;font-style:italic"> is not odr-usable due to intervening lambda-expression</SPAN>
    struct A {
      void f() { n = 2; } //<SPAN style="font-family:Times;font-style:italic"> error, </SPAN>n<SPAN style="font-family:Times;font-style:italic"> is not odr-usable due to intervening function definition scope</SPAN>
    };
    void g(int = n);      //<SPAN style="font-family:Times;font-style:italic"> error, </SPAN>n<SPAN style="font-family:Times;font-style:italic"> is not odr-usable due to intervening function parameter scope</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">    [=](int k = n) {};    //<SPAN style="font-family:Times;font-style:italic"> error, </SPAN>n<SPAN style="font-family:Times;font-style:italic"> is not odr-usable due to being outside the block scope of the lambda-expression</SPAN></SPAN>
    [&amp;] { [n]{ return n; }; }; //<SPAN style="font-family:Times;font-style:italic"> OK</SPAN>
  }
</PRE>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2381"></A><H4>2381.
  
Composite pointer type of pointers to plain and noexcept member functions
</H4><B>Section: </B>7.2.2&#160; [expr.type]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2018-06-19


<P>According to 7.3.13 [conv.fctptr] paragraph 1,</P>

<BLOCKQUOTE>

A prvalue of type &#8220;pointer to member of type <TT>noexcept</TT>
function&#8221; can be converted to a prvalue of type
&#8220;pointer to member of type function&#8221;. The result
designates the member function.

</BLOCKQUOTE>

<P>However, 7.2.2 [expr.type] paragraph 4 does not
allow for this conversion in determining the composite
pointer type of two pointers to member functions. The
corresponding conversion is considered for pointers to
non-member functions, but only qualification conversions are
considered for pointers to members:</P>

<BLOCKQUOTE>

<P>The <I>composite pointer type</I> of two
operands <TT>p1</TT> and <TT>p2</TT> having
types <TT>T1</TT> and <TT>T2</TT>, respectively, where at
least one is a pointer or pointer-to-member type
or <TT>std::nullptr_t</TT>, is:</P>

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

<LI><P>if <TT>T1</TT> or <TT>T2</TT> is &#8220;pointer to
noexcept function&#8221; and the other type is
&#8220;pointer to function&#8221;, where the function types
are otherwise the same, &#8220;pointer to
function&#8221;;</P></LI>

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

<LI>

<P>if <TT>T1</TT> is &#8220;pointer to member of <TT>C1</TT>
of type <I>cv1</I> <TT>U1</TT>&#8221; and <TT>T2</TT>
is &#8220;pointer to member of <TT>C2</TT> of type <I>cv2</I>
<TT>U2</TT>&#8221; where <TT>C1</TT> is reference-related
to <TT>C2</TT> or <TT>C2</TT> is reference-related
to <TT>C1</TT> (9.3.3 [dcl.init.ref]), the cv-combined
type of <TT>T2</TT> and <TT>T1</TT> or the cv-combined type
of <TT>T1</TT> and <TT>T2</TT>, respectively;</P></LI>

</UL>

</BLOCKQUOTE>

<P>Note also that the places that refer to &#8220;composite
pointer type&#8221; only refer to 7.3.12 [conv.mem]
for conversions involving pointers to members, omitting any
reference to 7.3.13 [conv.fctptr] for pointers to
member functions. This affects 7.6.9 [expr.rel],
7.6.10 [expr.eq], and 7.6.16 [expr.cond].</P>

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

<OL><LI><P>Change 7.2.2 [expr.type] paragraph 4 as follows:</P></LI>

<BLOCKQUOTE>

<P>The <I>composite pointer type</I> of two
operands <TT>p1</TT> and <TT>p2</TT> having
types <TT>T1</TT> and <TT>T2</TT>, respectively, where at
least one is a pointer or pointer-to-member type
or <TT>std::nullptr_t</TT>, is:</P>

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

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">if <TT>T1</TT> or <TT>T2</TT> is &#8220;pointer
to member of <TT>C1</TT> of type function&#8221;, the other
type is &#8220;pointer to member of <TT>C2</TT> of type
<TT>noexcept</TT> function&#8221;, and <TT>C1</TT> is
reference-related to <TT>C2</TT> or <TT>C2</TT> is
reference-related to <TT>C1</TT> (9.3.3 [dcl.init.ref]),
where the function types are otherwise the same, &#8220;pointer
to member of <TT>C2</TT> of type function&#8221; or
&#8220;pointer to member of <TT>C1</TT> of type function&#8221;,
respectively;</SPAN></P></LI>

<LI><P>if <TT>T1</TT> is &#8220;pointer to member
of <TT>C1</TT> of type <I>cv1</I> <SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>U1</TT></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>U</TT></SPAN>&#8221;
and <TT>T2</TT> is &#8220;pointer to member of <TT>C2</TT>
of type <I>cv2</I> <SPAN style="text-decoration:line-through;background-color:#FFA0A0"><TT>U2</TT></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0"><TT>U</TT></SPAN>&#8221;<SPAN style="font-weight:bold;background-color:#A0FFA0">, for some non-function
type <TT>U</TT>,</SPAN> where <TT>C1</TT> is
reference-related to <TT>C2</TT> or <TT>C2</TT> is
reference-related to <TT>C1</TT>
(9.3.3 [dcl.init.ref]), the cv-combined type
of <TT>T2</TT> and <TT>T1</TT> or the cv-combined type
of <TT>T1</TT> and <TT>T2</TT>, respectively;</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 7.6.10 [expr.eq] paragraph 4 as follows:</P></LI>

<BLOCKQUOTE>

If at least one of the operands is a pointer to member,
pointer-to-member conversions (7.3.12 [conv.mem])<SPAN style="font-weight:bold;background-color:#A0FFA0">,
function pointer conversions (7.3.13 [conv.fctptr]),</SPAN>
and qualification conversions (7.3.5 [conv.qual])
are performed on both operands to bring them to their
composite pointer type (7.2 [expr.prop]).
Comparing...

</BLOCKQUOTE>

<LI><P>Change 7.6.16 [expr.cond] bullet 7.4 as follows:</P></LI>

<BLOCKQUOTE>

<P>Lvalue-to-rvalue (7.3.1 [conv.lval]),
array-to-pointer (7.3.2 [conv.array]), and
function-to-pointer (7.3.3 [conv.func]) standard
conversions are performed on the second and third
operands. After those conversions, one of the following
shall hold:</P>

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

<LI><P>One or both of the second and third operands have
pointer-to-member type; pointer to member conversions
(7.3.12 [conv.mem])<SPAN style="font-weight:bold;background-color:#A0FFA0">, function pointer
conversions (7.3.13 [conv.fctptr]),</SPAN> and
qualification conversions (7.3.5 [conv.qual]) are
performed to bring them to their composite pointer type
(7.2 [expr.prop]). The result is of the composite
pointer type.</P></LI>

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

</UL>

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2384"></A><H4>2384.
  
Conversion function templates and qualification conversions
</H4><B>Section: </B>12.9.2.3&#160; [temp.deduct.conv]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2018-07-24


<P>Issue 349 resulted in the following
specification in 12.9.2.3 [temp.deduct.conv] paragraph 7:</P>

<BLOCKQUOTE>

<P>When the deduction process requires a qualification conversion for a
pointer or pointer-to-member type as described above, the following process
is used to determine the deduced template argument values: If <TT>A</TT>
is a type</P>

<UL><I>cv</I><SUB>1,0</SUB> &#8220;pointer to...&#8221; <I>cv</I><SUB>1,<I>n</I>-1</SUB> &#8220;pointer to&#8221; <I>cv</I><SUB>1,<I>n</I></SUB> <TT>T1</TT></UL>

<P>and <TT>P</TT> is a type</P>

<UL><I>cv</I><SUB>2,0</SUB> &#8220;pointer to...&#8221; <I>cv</I><SUB>2,<I>n</I>-1</SUB> &#8220;pointer to&#8221; <I>cv</I><SUB>2,<I>n</I></SUB> <TT>T2</TT></UL>

<P>then the cv-unqualified <TT>T1</TT> and <TT>T2</TT> are used as the
types of <TT>A</TT> and <TT>P</TT> respectively for type deduction.
[<I>Example:</I></P>

<PRE>
  struct A {
    template &lt;class T&gt; operator T***();
  };
  A a;
  const int * const * const * p1 = a; //<SPAN style="font-family:Times;font-style:italic"> </SPAN>T<SPAN style="font-family:Times;font-style:italic"> is deduced as </SPAN>int<SPAN style="font-family:Times;font-style:italic">, not </SPAN>const int
</PRE>

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

</BLOCKQUOTE>

<P>This rule is not widely implemented and may not be desirable. Should
it be removed?</P>

<P><B>Proposed resolutions (December, 2018):</B></P>

<P>Delete 12.9.2.3 [temp.deduct.conv] paragraph 7:</P>

<BLOCKQUOTE>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">When the deduction process requires a qualification conversion for a
pointer or pointer-to-member type as described above, the following process
is used to determine the deduced template argument values: If <TT>A</TT>
is a type</SPAN></P>

<UL><SPAN style="text-decoration:line-through;background-color:#FFA0A0"><I>cv</I><SUB>1,0</SUB> &#8220;pointer to...&#8221; <I>cv</I><SUB>1,<I>n</I>-1</SUB> &#8220;pointer to&#8221; <I>cv</I><SUB>1,<I>n</I></SUB> <TT>T1</TT></SPAN></UL>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">and <TT>P</TT> is a type</SPAN></P>

<UL><SPAN style="text-decoration:line-through;background-color:#FFA0A0"><I>cv</I><SUB>2,0</SUB> &#8220;pointer to...&#8221; <I>cv</I><SUB>2,<I>n</I>-1</SUB> &#8220;pointer to&#8221; <I>cv</I><SUB>2,<I>n</I></SUB> <TT>T2</TT></SPAN></UL>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">then the cv-unqualified <TT>T1</TT> and <TT>T2</TT> are used as the
types of <TT>A</TT> and <TT>P</TT> respectively for type deduction.
[<I>Example:</I></SPAN></P>

<PRE>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">  struct A {
    template &lt;class T&gt; operator T***();
  };
  A a;
  const int * const * const * p1 = a; //<SPAN style="font-family:Times;font-style:italic"> </SPAN>T<SPAN style="font-family:Times;font-style:italic"> is deduced as </SPAN>int<SPAN style="font-family:Times;font-style:italic">, not </SPAN>const int</SPAN>
</PRE>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">&#8212;<I>end example</I>]</SPAN></P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2385"></A><H4>2385.
  
Lookup for <I>conversion-function-id</I>s
</H4><B>Section: </B>7.5.4.2&#160; [expr.prim.id.qual]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2018-07-31


<P>According to 7.5.4.2 [expr.prim.id.qual] paragraph 5,</P>

<BLOCKQUOTE>

In a <I>qualified-id</I>, if the <I>unqualified-id</I> is
a <I>conversion-function-id</I>, its <I>conversion-type-id</I> shall denote
the same type in both the context in which the entire <I>qualified-id</I>
occurs and in the context of the class denoted by
the <I>nested-name-specifier</I>.

</BLOCKQUOTE>

<P>However, 6.4.5 [basic.lookup.classref] paragraph 7 says,</P>

<BLOCKQUOTE>

If the <I>id-expression</I> is a <I>conversion-function-id</I>,
its <I>conversion-type-id</I> is first looked up in the class of the object
expression and the name, if found, is used. Otherwise it is looked up in
the context of the entire <I>postfix-expression</I>. In each of these
lookups, only names that denote types or templates whose specializations
are types are considered.

</BLOCKQUOTE>

<P>The latter was changed by issue 1111. It
seems the former may have been overlooked in that change.</P>

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

<P>Change 7.5.4.2 [expr.prim.id.qual] paragraph 4 as follows:</P>

<BLOCKQUOTE>

In a <I>qualified-id</I>, if the <I>unqualified-id</I> is
a <I>conversion-function-id</I>,
its <I>conversion-type-id</I> <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall denote the same type in
both the context in which the entire <I>qualified-id</I>
occurs and in the context of the class denoted by
the <I>nested-name-specifier</I></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">is first looked up in the class denoted by the
<I>nested-name-specifier</I> of the <I>qualified-id</I> and
the name, if found, is used. Otherwise, it is looked up
in the context in which the entire <I>qualified-id</I>
occurs. In each of these lookups, only names that denote types
or templates whose specializations are types are considered</SPAN>.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2386"></A><H4>2386.
  
<T>tuple_size</T> requirements for structured binding
</H4><B>Section: </B>9.5&#160; [dcl.struct.bind]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Stephan T. Lavavej
 &#160;&#160;&#160;

 <B>Date: </B>2018-09-19


<P>According to 9.5 [dcl.struct.bind] paragraph 4,</P>

<BLOCKQUOTE>

Otherwise, if
the <I>qualified-id</I> <TT>std::tuple_size&lt;E&gt;</TT>
names a complete type, the
expression <TT>std::tuple_size&lt;E&gt;::value</TT> shall
be a well-formed integral constant expression and the number
of elements in the <I>identifier-list</I> shall be equal to
the value of that expression.

</BLOCKQUOTE>

<P>However, the common idiom in the library is that SFINAE tests the
presence or absence of a <TT>value</TT> member rather than the
completeness of the class; see 19.5.3.6 [tuple.helper] paragraph
4. The core language requirement should be changed to match the common
library practice.</P>

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

<P>Change 9.4 [dcl.fct.def] paragraph 4 as follows:</P>

<BLOCKQUOTE>

Otherwise, if the <I>qualified-id</I> <TT>std::tuple_size&lt;E&gt;</TT>
names a complete <SPAN style="font-weight:bold;background-color:#A0FFA0">class</SPAN> type <SPAN style="font-weight:bold;background-color:#A0FFA0">with a
member <TT>value</TT></SPAN>, the expression std::tuple_size&lt;E&gt;::value
shall be a well-formed integral constant expression and the number of
elements in the <I>identifier-list</I> shall be equal to the value of that
expression...

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2387"></A><H4>2387.
  
Linkage of const-qualified variable template
</H4><B>Section: </B>6.5&#160; [basic.link]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2018-09-28


<P>The list in 6.5 [basic.link] paragraph 3 specifying which
entities receive internal linkage does not mention variable templates,
so presumably a variable template has external linkage.
12 [temp] paragraph 6 gives the impression that a
specialization of a template with external linkage also has external
linkage. However, current implementations appear to give internal
linkage to specializations of const-qualified variable templates.
Should const-qualified variable templates have internal linkage?</P>

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

<P>CWG felt that a <TT>const</TT> type should not affect the
linkage of a variable template or its instances.</P>

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

<P>Change 6.5 [basic.link] paragraph 3 as follows:</P>

<BLOCKQUOTE>

<P>A name having namespace scope (6.3.6 [basic.scope.namespace])
has internal linkage if it is the name of</P>

<UL><LI><P>a variable, <SPAN style="font-weight:bold;background-color:#A0FFA0">variable template,</SPAN>
function or function template that is explicitly
declared <TT>static</TT>; or,</P></LI>

<LI><P>a non-inline <SPAN style="font-weight:bold;background-color:#A0FFA0">non-template</SPAN>
variable of non-volatile const-qualified
type that is neither explicitly declared <TT>extern</TT> nor
previously declared to have external linkage; or</P></LI>

<LI><P>a data member of an anonymous union.</P></LI>

</UL>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">[<I>Note:</I> An instantiated variable template that
has const-qualified type can have external linkage, even if
not declared <TT>extern</TT>. &#8212;<I>end
note</I>]</SPAN></P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2394"></A><H4>2394.
  
Const-default-constructible for members
</H4><B>Section: </B>10.3.4.1&#160; [class.default.ctor]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2018-07-10




<P>After the changes for comment RU 1 in
<A HREF="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0490r0.html">P0490R0</A>,
a defaulted default constructor is acceptable for default
initialization of a <TT>const</TT> object under certain
circumstances; for example,</P>

<PRE>
   struct A {};
   const A a;
</PRE>

<P>is well-formed. However, default-initialization of such a
class member still requires a user-provided constructor:</P>

<PRE>
   struct B { const A a; };
   B b;   //<SPAN style="font-family:Times;font-style:italic">error</SPAN>
</PRE>

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

<P>Change 10.3.4.1 [class.default.ctor] bullet 2.4 as follows:</P>

<BLOCKQUOTE>

<P>A defaulted default constructor for class <TT>X</TT> is
defined as deleted if:</P>

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

<LI><P>any non-variant non-static data member of
const-qualified type (or array thereof) with
no <I>brace-or-equal-initializer</I> <SPAN style="text-decoration:line-through;background-color:#FFA0A0">does not have a
user-provided default constructor</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">is not const-default-constructible
(9.3 [dcl.init])</SPAN> ,</P></LI>

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

</UL>

</BLOCKQUOTE>

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