<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;P0968R0</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Date:
     </TD>
<TD>
      &#160;2018-03-12</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
     March, 2018 (Jacksonville) meeting
    </H2>
</CENTER><BR><P>
    Section references in this document reflect the section numbering
    of document
    <A HREF="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4700.pdf">WG21 N4700</A>.
   </P>
<HR><A NAME="1893"></A><H4>1893.
  
Function-style cast with <I>braced-init-list</I>s and empty pack expansions
</H4><B>Section: </B>8.2.3&#160; [expr.type.conv]
 &#160;&#160;&#160;

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

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

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




<P>According to 8.2.3 [expr.type.conv] paragraph 1,</P>

<BLOCKQUOTE>

A <I>simple-type-specifier</I> (10.1.7.2 [dcl.type.simple])
or <I>typename-specifier</I> (17.7 [temp.res]) followed by a
parenthesized <I>expression-list</I> constructs a value of the specified
type given the expression list. If the expression list is a single
expression, the type conversion expression is equivalent (in definedness,
and if defined in meaning) to the corresponding cast expression
(8.4 [expr.cast]). If the type specified is a class type, the
class type shall be complete. If the expression list specifies more than a
single value, the type shall be a class with a suitably declared
constructor (11.6 [dcl.init], 15.1 [class.ctor]), and the
expression <TT>T(x1, x2, ...)</TT> is equivalent in effect to the
declaration <TT>T t(x1, x2, ...);</TT> for some invented temporary
variable <TT>t</TT>, with the result being the value of <TT>t</TT> as a
prvalue.

</BLOCKQUOTE>

<P>This does not cover the cases when the <I>expression-list</I>
contains a single <I>braced-init-list</I> (which is neither an
expression nor more than a single value) or if it contains no
expressions as the result of an empty pack expansion.</P>

<P><b>Proposed resolution (June, 2014): [SUPERSEDED]</b></P>

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

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

<P>Change 8.2.3 [expr.type.conv] paragraph 2 as follows:</P>

<BLOCKQUOTE>

If the initializer is a parenthesized single expression, the type
conversion expression is equivalent to the corresponding cast expression
(8.4 [expr.cast]). Otherwise, if the type is <I>cv</I>
<TT>void</TT> and the initializer is <TT>()</TT> <SPAN style="font-weight:bold;background-color:#A0FFA0">(after pack
expansion, if any)</SPAN>, the expression is a prvalue of the specified type
that performs no initialization. Otherwise, the expression is a prvalue of
the specified type whose result object is direct-initialized
(11.6 [dcl.init]) with the initializer. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">For an expression of
the form <TT>T()</TT>, <TT>T</TT></SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">If the initializer is a
parenthesized optional <I>expression-list</I>, the specified type</SPAN>
shall not be an array type.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="1910"></A><H4>1910.
  
&#8220;Shall&#8221; requirement applied to runtime behavior
</H4><B>Section: </B>6.7.4.1&#160; [basic.stc.dynamic.allocation]
 &#160;&#160;&#160;

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

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

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




<P>According to 6.7.4.1 [basic.stc.dynamic.allocation] paragraph 3,</P>

<BLOCKQUOTE>

If an allocation function declared with a
non-throwing <I>exception-specification</I> (18.4 [except.spec])
fails to allocate storage, it shall return a null pointer. Any other
allocation function that fails to allocate storage shall indicate failure
only by throwing an exception (18.1 [except.throw]) of a type that
would match a handler (18.3 [except.handle]) of
type <TT>std::bad_alloc</TT> (21.6.3.1 [bad.alloc]).

</BLOCKQUOTE>

<P>The use of the word &#8220;shall&#8221; to constrain runtime behavior
is inappropriate, as it normally identifies cases requiring a compile-time
diagnostic.</P>

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

<OL><LI><P>Change 6.7.4 [basic.stc.dynamic] paragraph 3 as follows:</P></LI>

<BLOCKQUOTE>

<SPAN style="text-decoration:line-through;background-color:#FFA0A0">Any allocation and/or deallocation functions defined in a C ++
program, including the default versions in the library, shall conform to
the semantics</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">If the behavior of an allocation or deallocation
function does not satisfy the semantic constraints</SPAN> specified in
6.7.4.1 [basic.stc.dynamic.allocation] and 6.7.4.2 [basic.stc.dynamic.deallocation]<SPAN style="font-weight:bold;background-color:#A0FFA0">, the
behavior is undefined</SPAN>.

</BLOCKQUOTE>

<LI><P>Change 6.7.4.1 [basic.stc.dynamic.allocation] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

...The value of the first parameter <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall be</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">is</SPAN>
interpreted as the requested size of the allocation...

</BLOCKQUOTE>

<LI><P>Change 6.7.4.1 [basic.stc.dynamic.allocation] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

<SPAN style="text-decoration:line-through;background-color:#FFA0A0">The</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">An</SPAN> allocation function attempts to allocate the
requested amount of storage. If it is successful, it <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall return</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">returns</SPAN> the address of the start of a block of storage whose
length in bytes <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall be</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">is</SPAN> at least as large as the requested size. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">There are no
constraints on the contents of the allocated storage on return from the
allocation function.</SPAN> The order, contiguity, and initial value of
storage allocated by successive calls to an allocation function are
unspecified. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">The</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">For an allocation function other than a
reserved placement allocation function (21.6.2.3 [new.delete.placement],
the</SPAN> pointer returned <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall be</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">is</SPAN> suitably
aligned so that it can be converted to a pointer to any suitable complete
object type (21.6.2.1 [new.delete.single]) and then used to access the
object or array in the storage allocated (until the storage is explicitly
deallocated by a call to a corresponding deallocation function). Even if
the size of the space requested is zero, the request can fail. If the
request succeeds, the value returned <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall be</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">by a
replaceable allocation function is</SPAN> a non-null pointer value
(7.11 [conv.ptr]) <TT>p0</TT> different from any previously
returned value <TT>p1</TT>, unless that value <TT>p1</TT> was subsequently
passed to <SPAN style="text-decoration:line-through;background-color:#FFA0A0">an operator delete</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">a replaceable deallocation
function</SPAN>. Furthermore, for the library allocation
functions in 21.6.2.1 [new.delete.single] and
21.6.2.2 [new.delete.array], <TT>p0</TT> <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall represent</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">represents</SPAN> the address of a block of storage disjoint from the
storage for any other object accessible to the caller. The effect of
indirecting through a pointer returned <SPAN style="text-decoration:line-through;background-color:#FFA0A0">as</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">from</SPAN>
a request for zero size is undefined.<SUP>38</SUP>

</BLOCKQUOTE>

<LI><P>Change 6.7.4.1 [basic.stc.dynamic.allocation] paragraph 3 as follows:</P></LI>

<BLOCKQUOTE>

An allocation function that fails to allocate storage can invoke the
currently installed new-handler function (21.6.3.3 [new.handler]),
if any. [<I>Note:</I> A program-supplied allocation function can obtain the
address of the currently installed <TT>new_handler</TT> using the
<TT>std::get_new_handler</TT> function
(21.6.3.4 [set.new.handler]). &#8212;<I>end note</I>] <SPAN style="text-decoration:line-through;background-color:#FFA0A0">If an</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">An</SPAN> allocation function that has a non-throwing exception
specification (18.4 [except.spec]) <SPAN style="text-decoration:line-through;background-color:#FFA0A0">fails to allocate storage,
it shall return</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">indicates failure by returning</SPAN> a null
pointer <SPAN style="font-weight:bold;background-color:#A0FFA0">value</SPAN>. Any other allocation function <SPAN style="text-decoration:line-through;background-color:#FFA0A0">that fails to
allocate storage shall indicate</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">never returns a null pointer
value and indicates</SPAN> failure only by throwing an exception
(18.1 [except.throw]) of a type that would match a handler
(18.3 [except.handle]) of type <TT>std::bad_alloc</TT>
(21.6.3.1 [bad.alloc]).

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="1983"></A><H4>1983.
  
Inappropriate use of <I>virt-specifier</I>
</H4><B>Section: </B>12.2&#160; [class.mem]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2014-08-11


<P>The restriction in 12.2 [class.mem] paragraph 8 that a
<I>virt-specifier</I> may appear only in the declaration of a virtual
function is insufficient to rule out examples like the following:</P>

<PRE>
  struct A { virtual void f(); };
  struct B { friend void A::f() final; };

  template&lt;typename T&gt; struct C { virtual void f() {} };
  template void C&lt;int&gt;::f() final;
  template&lt;&gt; void C&lt;char&gt;::f() final;
</PRE>

<P>One possibility might be to require that a <I>virt-specifier</I>
appear only on the first declaration of a function.</P>

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

<P>Change 12.2 [class.mem] paragraph 13 as follows:</P>

<BLOCKQUOTE>

A <I>virt-specifier-seq</I> shall contain at most one of
each <I>virt-specifier</I>. A <I>virt-specifier-seq</I> shall appear only
in the <SPAN style="font-weight:bold;background-color:#A0FFA0">first</SPAN> declaration of a virtual member function
(13.3 [class.virtual]).

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2059"></A><H4>2059.
  
Linkage and deduced return types
</H4><B>Section: </B>10.1.7.4&#160; [dcl.spec.auto]
 &#160;&#160;&#160;

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

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

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




<P>Use of function return type deduction makes it possible to
define functions whose return type is a type without linkage.
Although 6.5 [basic.link] paragraph 8 permits such a
usage if the function is defined in the same translation unit
as it is used, it may be helpful to consider changing the overall
rules regarding the use of types with internal or no linkage.
As an example, the following example permits access to a local
static variable that has not been initialized:</P>

<PRE>
  auto f() {
    static int n = 123;
    struct X { int &amp;f() { return n; } };
    return X();
  }
  int &amp;r = decltype(f())().f();
</PRE>

<P><B>Notes from the February, 2016 meeting:</B></P>

<P>CWG agreed that the current rule in
6.5 [basic.link] paragraph 8 is unneeded; the ODR
already prohibits use of an entity that is not defined in
the current translation unit and cannot be defined in a
different translation unit.</P>

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

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

<BLOCKQUOTE>

<P>...<SPAN style="text-decoration:line-through;background-color:#FFA0A0">A type without linkage shall not be used as the type of a
variable or function with external linkage unless</SPAN></P>

<UL><LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">the entity has C language linkage
(10.5 [dcl.link]), or</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">the entity is declared within an unnamed namespace
(10.3.1 [namespace.def]), or</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">the entity is not odr-used (6.2 [basic.def.odr]) or is
defined in the same translation unit.</SPAN></P></LI>

</UL>

<P>[<I>Note:</I> In other words, a type without linkage contains a class or
enumeration that cannot be named outside its translation unit. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">An
entity with external linkage declared using such a type could not
correspond to any other entity in another translation unit of the program
and thus must be defined in the translation unit if it is odr-used. Also
note that classes</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">Classes</SPAN> with linkage may contain members
whose types do not have linkage<SPAN style="text-decoration:line-through;background-color:#FFA0A0">, and that typedef</SPAN><SPAN style="font-weight:bold;background-color:#A0FFA0">.
Typedef</SPAN> names are ignored in the determination of whether a type has
linkage. &#8212;<I>end note</I>] [<I>Example:</I></P>

<PRE>
  template &lt;class T&gt; struct B {
    void g(T) { }
    void h(T);
    friend void i(B, T) { }
  };

  void f() {
    struct A { int x; };  //<SPAN style="font-family:Times;font-style:italic"> no linkage</SPAN>
    A a = { 1 };
    B&lt;A&gt; ba;              //<SPAN style="font-family:Times;font-style:italic"> declares </SPAN>B&lt;A&gt;::g(A)<SPAN style="font-family:Times;font-style:italic"> and </SPAN>B&lt;A&gt;::h(A)
    ba.g(a);              //<SPAN style="font-family:Times;font-style:italic"> OK</SPAN>
    ba.h(a);              //<SPAN style="font-family:Times;font-style:italic"> error: </SPAN>B&lt;A&gt;::h(A)<SPAN style="font-family:Times;font-style:italic"> not defined<SPAN style="font-weight:bold;background-color:#A0FFA0">; </SPAN></SPAN><SPAN style="font-weight:bold;background-color:#A0FFA0">A</SPAN><SPAN style="font-family:Times;font-style:italic"><SPAN style="font-weight:bold;background-color:#A0FFA0"> cannot be named</SPAN> in <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">another</SPAN> translation unit</SPAN>
    i(ba, a);             //<SPAN style="font-family:Times;font-style:italic"> OK</SPAN>
  }
</PRE>

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

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2081"></A><H4>2081.
  
Deduced return type in redeclaration or specialization of function template
</H4><B>Section: </B>10.1.7.4&#160; [dcl.spec.auto]
 &#160;&#160;&#160;

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

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

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


<P>10.1.7.4 [dcl.spec.auto] paragraph 13 says,</P>

<BLOCKQUOTE>

Redeclarations or specializations of a function or function
template with a declared return type that uses a placeholder
type shall also use that placeholder, not a deduced type.

</BLOCKQUOTE>

<P>The inverse should also be true (a specialization cannot use
a placeholder type if the template used a non-placeholder), but
this is not said explicitly.</P>

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

<P>Change 10.1.7.4 [dcl.spec.auto] paragraph 11 as follows:</P>

<BLOCKQUOTE>

Redeclarations or specializations of a function or function template with a
declared return type that uses a placeholder type shall also use that
placeholder, not a deduced type. <SPAN style="font-weight:bold;background-color:#A0FFA0">Similarly, redeclarations or
specializations of a function or function template with a declared return
type that does not use a placeholder type shall not use a
placeholder.</SPAN> [<I>Example:</I>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2088"></A><H4>2088.
  
Late tiebreakers in partial ordering
</H4><B>Section: </B>17.9.2.4&#160; [temp.deduct.partial]
 &#160;&#160;&#160;

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

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

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




<P>The late tiebreakers for lvalue-vs-rvalue references and
cv-qualification in 17.9.2.4 [temp.deduct.partial] paragraph 9 are
applied</P>

<BLOCKQUOTE>

If, for a given type, deduction succeeds in both directions
(i.e., the types are identical after the transformations
above) and both <TT>P</TT> and <TT>A</TT> were reference
types (before being replaced with the type referred to
above):

</BLOCKQUOTE>

<P>However, this is based on a false assumption.  For
example,</P>

<PRE>
  template &lt;typename T&gt; struct A {
    struct typeA { };
    struct typeB { };
    using convTyA = T (*const &amp;&amp;)(typename A&lt;T&gt;::typeA);
    using convTyB = T (*const &amp;)(typename A&lt;T&gt;::typeB);
    operator convTyA();
    operator convTyB();
  };

  template &lt;typename T&gt; void foo(T (*const &amp;&amp;)(typename A&lt;T&gt;::typeA));
  template &lt;typename T&gt; int foo(T (*const &amp;)(typename A&lt;T&gt;::typeB));

  int main() {
    return foo&lt;int&gt;(A&lt;int&gt;());
  }
</PRE>

<P>(see also issues 1847 and
1157.).  We need to
decide whether the rule is &#8220;deduction succeeds in both
directions&#8221; or &#8220;the types are identical.&#8221;  The
latter seems more reasonable.</P>

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

<P>Change 17.9.2.4 [temp.deduct.partial] paragraph 9 as follows:</P>

<BLOCKQUOTE>

<P>If, for a given type, <SPAN style="text-decoration:line-through;background-color:#FFA0A0">deduction succeeds in both directions
(i.e.,</SPAN> the types are identical after the transformations
above<SPAN style="text-decoration:line-through;background-color:#FFA0A0">)</SPAN> and both <TT>P</TT> and <TT>A</TT> were reference types
(before being replaced with the type referred to above):</P>

<UL><LI><P>if the type from the argument template was an lvalue reference
and the type from the parameter template was not, the parameter type is not
considered to be at least as specialized as the argument type;
otherwise,</P></LI>

<LI><P>if the type from the argument template is more cv-qualified than the
type from the parameter template (as described above), the parameter type
is not considered to be at least as specialized as the argument
type.</P></LI>

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2092"></A><H4>2092.
  
Deduction failure and overload resolution
</H4><B>Section: </B>17.9.3&#160; [temp.over]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2015-03-06




<P>Given an example like</P>

<PRE>
  template &lt;class T = int&gt; void foo(T*);

  void test()
  {
    foo(0);   //<SPAN style="font-family:Times;font-style:italic"> #1 valid?</SPAN>
    foo&lt;&gt;(0);  //<SPAN style="font-family:Times;font-style:italic"> #2 valid?</SPAN>
  }
</PRE>

<P>most/all implementations reject this code.  However, the wording
of the Standard only invokes 17.9.3 [temp.over]
(&#8220;Overload resolution&#8221;) in cases where there is more
than one function or function template, which is not the case here.
The current wording would appear to make this well-formed because
of the application of 17.9.1 [temp.arg.explicit] paragraph 2.
Perhaps overload resolution should apply even when there is a single
function template?</P>

<P><B>Notes from the May, 2015 meeting:</B></P>

<P>This issue is mostly a duplicate of
issue 1582. However, CWG felt that it
should be clarified that overload resolution applies in all cases,
not just when templates are overloaded, so the issue is being left
open to deal with that aspect.</P>

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

<OL><LI><P>Change 8.2.2 [expr.call] paragraph 1, splitting
it into three paragraphs, as follows:</P></LI>

<BLOCKQUOTE>

<P>A function call is a postfix expression followed by parentheses containing
a possibly empty, comma-separated list of <I>initializer-clause</I>s which
constitute the arguments to the function. The postfix expression shall have
function type or function pointer type. For a call to a non-member function
or to a static member function, the postfix expression shall be either an
lvalue that refers to a function (in which case the function-to-pointer
standard conversion (7.3 [conv.func]) is suppressed on the postfix
expression), or it shall have function pointer type.  <SPAN style="text-decoration:line-through;background-color:#FFA0A0">Calling a function
through an expression whose function type is different from the function
type of the called function's definition results in undefined behavior
(10.5 [dcl.link]).</SPAN></P>

<P>For a call to a non-static member function, the postfix expression shall
be an implicit (12.2.2 [class.mfct.non-static], 12.2.3 [class.static])
or explicit class member access (8.2.5 [expr.ref]) whose
<I>id-expression</I> is a function member name, or a pointer-to-member
expression (8.5 [expr.mptr.oper]) selecting a function member; the call
is as a member of the class object referred to by the object expression. In
the case of an implicit class member access, the implied object is the one
pointed to by <TT>this</TT>. [<I>Note:</I> A member function call of the
form <TT>f()</TT> is interpreted as <TT>(*this).f()</TT> (see
12.2.2 [class.mfct.non-static]). &#8212;<I>end note</I>]</P>

<P>If a function or member function name is used, <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the name can be
overloaded (Clause 16 [over]), in which case</SPAN> the
appropriate function <SPAN style="text-decoration:line-through;background-color:#FFA0A0">shall be selected</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">and the validity of
the call are determined</SPAN> according to the rules in
16.3 [over.match]. If the selected function is non-virtual, or if
the <I>id-expression</I> in the class member access expression is a
qualified-id, that function is called. Otherwise, its final overrider
(13.3 [class.virtual]) in the dynamic type of the object expression is
called; such a call is referred to as a <I>virtual function
call</I>. [<I>Note:</I> The dynamic type is the type of the object referred
to by the current value of the object expression. 15.7 [class.cdtor]
describes the behavior of virtual function calls when the object expression
refers to an object under construction or destruction.  &#8212;<I>end
note</I>]</P>

</BLOCKQUOTE>

<LI><P>Add the following to 8.2.2 [expr.call] as a new paragraph
before the existing paragraph 4:</P></LI>

<BLOCKQUOTE>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">Calling a function through an expression whose function type is different from the function type of the called function's  definition results in undefined behavior (10.5 [dcl.link]).</SPAN>
</P>

<P>When a function is called, each parameter (11.3.5 [dcl.fct])
shall be initialized...</P>

</BLOCKQUOTE>

<LI><P>Change 16 [over] paragraph 2 as follows:</P></LI>

<BLOCKQUOTE>

When <SPAN style="text-decoration:line-through;background-color:#FFA0A0">an overloaded</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">a</SPAN> function name is used in a call,
which <SPAN style="text-decoration:line-through;background-color:#FFA0A0">overloaded</SPAN> function declaration is being
referenced <SPAN style="text-decoration:line-through;background-color:#FFA0A0">is</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">and the validity of the call are</SPAN>
determined by comparing the types of the arguments at the point of use with
the types of the parameters in the <SPAN style="text-decoration:line-through;background-color:#FFA0A0">overloaded</SPAN> declarations that
are visible at the point of use. This function selection process is
called <I>overload resolution</I>...

</BLOCKQUOTE>

<LI><P>Change 17.9.3 [temp.over] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

<SPAN style="text-decoration:line-through;background-color:#FFA0A0">A function template can be overloaded either by (non-template)
functions of its name or by (other) function templates of the same
name.</SPAN> When a call to <SPAN style="text-decoration:line-through;background-color:#FFA0A0">that</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">the</SPAN> name <SPAN style="font-weight:bold;background-color:#A0FFA0">of a
function or function template</SPAN> is written (explicitly, or implicitly
using the operator notation), template argument deduction...

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2164"></A><H4>2164.
  
Name hiding and <I>using-directive</I>s
</H4><B>Section: </B>6.3.10&#160; [basic.scope.hiding]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2015-07-26




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

<PRE>
   const int i = -1;
   namespace T {
     namespace N { const int i = 1; }
     namespace M {
       using namespace N;
       int a[i];
     }
   }
</PRE>

<P>According to 6.4.1 [basic.lookup.unqual], lookup for
<TT>i</TT> finds <TT>T::N::i</TT> and stops.  However,
according to 6.3.10 [basic.scope.hiding] paragraph 1,
the appearance of <TT>T::N::i</TT> in namespace <TT>T</TT>
does <I>not</I> hide <TT>::i</TT>, so both declarations of
<TT>i</TT> are visible in the declaration of <TT>a</TT>.</P>

<P>It seems strange that we specify this name hiding rule
in two different ways in two different places, but they
should at least be consistent.</P>

<P>On a related note, the wording in 6.4.1 [basic.lookup.unqual]
paragraph 2, &#8220;as if they were declared in the nearest
enclosing namespace...&#8221; could be confusing with regard to
the &#8220;declared in the same scope&#8221; provisions of
6.3.10 [basic.scope.hiding].</P>

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

<P>Change 6.3.10 [basic.scope.hiding] paragraphs 1 and 2 as follows:</P>

<BLOCKQUOTE>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">A name can be hidden by an explicit declaration of that same name
in a nested declarative region or derived class
(13.2 [class.member.lookup])</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">A declaration of a name in a nested
declarative region hides a declaration of the same name in an enclosing
declarative region; see 6.3.1 [basic.scope.declarative] and
6.4.1 [basic.lookup.unqual]</SPAN>.</P>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">A class name (12.1 [class.name]) or enumeration name
(10.2 [dcl.enum]) can be hidden by the name of a variable, data
member, function, or enumerator declared in the same scope.</SPAN> If a
class <SPAN style="font-weight:bold;background-color:#A0FFA0">name (12.1 [class.name])</SPAN> or enumeration
name <SPAN style="font-weight:bold;background-color:#A0FFA0">(10.2 [dcl.enum])</SPAN> and a variable, data member,
function, or enumerator are declared in the same <SPAN style="text-decoration:line-through;background-color:#FFA0A0">scope</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">declarative region</SPAN> (in any order) with the same
name <SPAN style="font-weight:bold;background-color:#A0FFA0">(excluding declarations made visible via <I>using-directive</I>s
(6.4.1 [basic.lookup.unqual]))</SPAN>, the class or enumeration name is
hidden wherever the variable, data member, function, or enumerator name is
visible.</P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2226"></A><H4>2226.
  
Xvalues vs lvalues in conditional expressions
</H4><B>Section: </B>8.16&#160; [expr.cond]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2016-02-01




<P>In the following example,</P>

<PRE>
   const T a; 
   T b; 
   false ? a : std::move(b); 
</PRE>

<P>the most appropriate result would seem to be that the expression is
an lvalue of type <TT>const T</TT> that refers to either <TT>a</TT> or
<TT>b</TT>. However, because 8.16 [expr.cond] bullet 4.1
requires that the conversion bind directly to an lvalue, while
<TT>std::move(b)</TT> is an xvalue, the result is a <TT>const T</TT>
temporary copy-initialized from <TT>std::move(b)</TT>.</P>

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

<P>Change 8.16 [expr.cond] bullet 4.1 as follows:</P>

<BLOCKQUOTE>

<P>Attempts are made to form an implicit conversion sequence from an
operand expression <TT>E1</TT> of type <TT>T1</TT> to a target type related
to the type <TT>T2</TT> of the operand expression <TT>E2</TT> as
follows:</P>

<UL><LI><P>If <TT>E2</TT>
is an lvalue, the target type is &#8220;lvalue reference to
<TT>T2</TT>&#8221;, subject to the constraint that in the conversion the
reference must bind directly (11.6.3 [dcl.init.ref]) to <SPAN style="text-decoration:line-through;background-color:#FFA0A0">an
lvalue</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">a glvalue</SPAN>.</P></LI>

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

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2227"></A><H4>2227.
  
Destructor access and default member initializers
</H4><B>Section: </B>15.6.2&#160; [class.base.init]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2016-02-01




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

<PRE>
   class X { ~X(); }; 
   struct Y { X x = {}; }; 
</PRE>

<P>Should <TT>X</TT>'s destructor be potentially invoked by this attempt
to initialize an <TT>X</TT> object? Or,</P>

<PRE>
   auto *y = new Y {}; 
</PRE>

<P>No constructor for <TT>Y</TT> is used, because this is aggregate
initialization, and a destructor for <TT>X</TT> is not strictly necessary
as there is no later initialization that might throw, but in the
corresponding default constructor case we do require that the destructor
be valid.</P>

<P>Perhaps the most consistent answer is that the default member
initializer should not potentially invoke the destructor unless it's used
(for symmetry with default arguments), but that aggregate initialization
should potentially invoke the destructors of all subobjects (including the
final one - exceptions could theoretically be thrown between the completion
of the construction of the final aggregate element and the notional
completion of the construction of the aggregate itself.</P>

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

<OL><LI><P>Add the following as a new paragraph following
11.6.1 [dcl.init.aggr] paragraph 7:</P></LI>

<BLOCKQUOTE>

<P>An aggregate that is a class can also be initialized with a single
expression not enclosed in braces, as described in
11.6 [dcl.init].</P>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">The destructor for each element of class type is potentially
invoked (15.4 [class.dtor]) from the context where the aggregate
initialization occurs. [<I>Note:</I> This provision ensures that
destructors can be called for fully-constructed subobjects in case an
exception is thrown (18.2 [except.ctor]). &#8212;<I>end
note</I>]</SPAN></P>

</BLOCKQUOTE>

<LI><P>Change 15.4 [class.dtor] paragraph 12 as follows:</P>

<BLOCKQUOTE>

...A destructor is <I>potentially invoked</I> if it is invoked or as
specified in
8.3.4 [expr.new], <SPAN style="font-weight:bold;background-color:#A0FFA0">11.6.1 [dcl.init.aggr],</SPAN>
15.6.2 [class.base.init], and 18.1 [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>
</LI>

</OL>

<BR><BR><HR><A NAME="2229"></A><H4>2229.
  
Volatile unnamed bit-fields
</H4><B>Section: </B>12.2.4&#160; [class.bit]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>David Majnemer
 &#160;&#160;&#160;

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


<P>According to 12.2.4 [class.bit] paragraph 2, unnamed bit-fields
are not members, but there does not appear to be a prohibition against
their being declared <TT>volatile</TT>. Is this intended?</P>

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

<P>Change 12.2.4 [class.bit] paragraph 2 as follows:</P>

<BLOCKQUOTE>

A declaration for a bit-field that omits the <I>identifier</I> declares an
<I>unnamed bit-field</I>. Unnamed bit-fields are not members and cannot be
initialized. <SPAN style="font-weight:bold;background-color:#A0FFA0">An unnamed bit-field shall not be declared with a
cv-qualified type.</SPAN> [<I>Note:</I> An unnamed bit-field is useful for
padding...

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2234"></A><H4>2234.
  
Missing rules for <I>simple-template-id</I> as <I>class-name</I>
</H4><B>Section: </B>12&#160; [class]
 &#160;&#160;&#160;

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

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

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




<P>There does not seem to be a rule that prohibits an example like:</P>

<PRE>
  template&lt;typename T&gt; struct X; 
  struct X&lt;int&gt; { 
  }; 
</PRE>

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

<P><B>Change 12 [class] paragraph 1 as follows:</B></P>

<BLOCKQUOTE>

...<SPAN style="font-weight:bold;background-color:#A0FFA0">A class declaration where the <I>class-name</I> in the
<I>class-head-name</I> is a <I>simple-template-id</I> shall be an explicit
specialization (17.8.3 [temp.expl.spec]) or a partial specialization
(17.6.5 [temp.class.spec]).</SPAN> A <I>class-specifier</I>
whose <I>class-head</I> omits the <I>class-head-name</I> defines an unnamed
class. [<I>Note:</I> An unnamed class thus can't be final. &#8212;<I>end
note</I>]

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2235"></A><H4>2235.
  
Partial ordering and non-dependent types
</H4><B>Section: </B>17.9.2.4&#160; [temp.deduct.partial]
 &#160;&#160;&#160;

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

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

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




<P>Paragraph 12 of 17.9.2.4 [temp.deduct.partial] contains the following
example:</P>

<PRE>
  template &lt;class T&gt; T f(int);        //<SPAN style="font-family:Times;font-style:italic"> #1</SPAN>
  template &lt;class T, class U&gt; T f(U); //<SPAN style="font-family:Times;font-style:italic"> #2</SPAN>
  void g() {
    f&lt;int&gt;(1);                        //<SPAN style="font-family:Times;font-style:italic"> calls #1</SPAN>
  }
</PRE>

<P>However, paragraph 4 states,</P>

<BLOCKQUOTE>

If a particular <TT>P</TT> contains no <I>template-parameter</I>s that
participate in template argument deduction, that <TT>P</TT> is not used to
determine the ordering.

</BLOCKQUOTE>

<P>Thus, we ignore the <TT>P=int</TT>, <TT>A=U</TT> case and deduction
succeeds for the <TT>P=U</TT>, <TT>A=int</TT> case, so both templates
are at least as specialized as each other. And consider:</P>

<PRE>
  template &lt;class... T&gt; struct V {}; 
  template &lt;class... Ts, class... Us&gt; void Foo(V&lt;Ts...&gt;, V&lt;Us&amp;...&gt;) {} //<SPAN style="font-family:Times;font-style:italic"> #3 </SPAN>
  template &lt;class... Us&gt; void Foo(V&lt;&gt;, V&lt;Us&amp;...&gt;) {}                   //<SPAN style="font-family:Times;font-style:italic"> #4 </SPAN>
  void h() { 
    Foo(V&lt;&gt;(), V&lt;&gt;()); 
  } 
</PRE>

<P>The intent is that this should call #4; that template clearly ought to
be more specialized.</P>

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

<OL><LI><P>Change 17.9.2.4 [temp.deduct.partial] paragraph 4 as
follows:</P></LI>:

<BLOCKQUOTE>

Each type nominated above from the parameter template and the corresponding
type from the argument template are used as the types of <TT>P</TT>
and <TT>A</TT>. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">If a particular <TT>P</TT> contains
no <I>template-parameter</I>s that participate in template argument
deduction, that <TT>P</TT> is not used to determine the ordering.</SPAN>

</BLOCKQUOTE>

<LI><P>Change 17.9.2.5 [temp.deduct.type] paragraph 4 as follows:</P></LI>

<BLOCKQUOTE>

...If a template parameter is used only in non-deduced contexts and is not
explicitly specified, template argument deduction fails. [<I>Note:</I>
Under 17.9.2.1 [temp.deduct.call] <SPAN style="text-decoration:line-through;background-color:#FFA0A0">and
17.9.2.4 [temp.deduct.partial]</SPAN>, if <TT>P</TT> contains
no <I>template-parameter</I>s that appear in deduced contexts, no deduction
is done, so <TT>P</TT> and <TT>A</TT> need not have the same
form. &#8212;<I>end note</I>]

</BLOCKQUOTE>

</OL>

<BR><BR><HR><A NAME="2237"></A><H4>2237.
  
Can a <I>template-id</I> name a constructor?
</H4><B>Section: </B>15.1&#160; [class.ctor]
 &#160;&#160;&#160;

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

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

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




<P>Bullet 1.2 of 15.1 [class.ctor], describing declarator forms
that are considered to declare a constructor, says:</P>

<BLOCKQUOTE>

<P>...and the <I>id-expression</I> has one of the following forms:</P>

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

<LI><P>in a <I>member-declaration</I> that belongs to
the <I>member-specification</I> of a class template but is not a friend
declaration, the <I>id-expression</I> is a <I>class-name</I> that names the
current instantiation (17.7.2.1 [temp.dep.type]) of the
immediately-enclosing class template; or</P></LI>

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

</UL>

</BLOCKQUOTE>

<P>The term <I>class-name</I> includes <I>simple-template-id</I>. It is
not clear that allowing a constructor declaration of the form</P>

<PRE>
  template&lt;class T&gt; struct X { 
    X&lt;T&gt;(T); //<SPAN style="font-family:Times;font-style:italic"> constructor </SPAN>
  }; 
</PRE>

<P>is useful or helpful.</P>

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

<OL><LI><P>Change 15.1 [class.ctor] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

<P>...and the <I>id-expression</I> has one of the following forms:</P>

<UL><LI><P>in a <I>member-declaration</I> that belongs to
the <I>member-specification</I> of a class <SPAN style="font-weight:bold;background-color:#A0FFA0">or class template</SPAN> but
is not a friend declaration (14.3 [class.friend]),
the <I>id-expression</I> is the injected-class-name (Clause
12 [class]) of the immediately-enclosing <SPAN style="text-decoration:line-through;background-color:#FFA0A0">class;</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">entity or</SPAN></P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">in a <I>member-declaration</I> that belongs to
the <I>member-specification</I> of a class template but is not a friend
declaration, the <I>id-expression</I> is a <I>class-name</I> that names the
current instantiation (17.7.2.1 [temp.dep.type]) of the
immediately-enclosing class template; or</SPAN></P></LI>

<LI><P>in a declaration at namespace scope or in a friend declaration,
the <I>id-expression</I> is a <I>qualified-id</I> that names a constructor
(6.4.3.1 [class.qual]).</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 15.4 [class.dtor] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

<P>...and the <I>id-expression</I> has one of the following forms:</P>

<UL><LI>

<P>in a <I>member-declaration</I> that belongs to
the <I>member-specification</I> of a class <SPAN style="font-weight:bold;background-color:#A0FFA0">or class template</SPAN>
but is not a friend declaration
(14.3 [class.friend]), the <I>id-expression</I>
is <TT>~</TT><I>class-name</I> and the <I>class-name</I> is the
injected-class-name (Clause 12 [class]) of the
immediately-enclosing <SPAN style="text-decoration:line-through;background-color:#FFA0A0">class;</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">entity or</SPAN></P></LI>

<LI>

<P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">in a <I>member-declaration</I> that belongs to
the <I>member-specification</I> of a class template but is not a friend
declaration, the <I>id-expression</I> is <TT>~</TT><I>class-name</I> and
the <I>class-name</I> names the current instantiation
(17.7.2.1 [temp.dep.type]) of the immediately-enclosing class
template; or</SPAN></P></LI>

<LI>

<P>in a declaration at namespace scope or in a friend declaration,
the <I>id-expression</I>
is <I>nested-name-specifier</I> <TT>~</TT><I>class-name</I> and
the <I>class-name</I> names the same class as the
<I>nested-name-specifier</I>.</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Add the following as a new paragraph in
C.5 [diff.cpp17]:</P></LI>

<BLOCKQUOTE>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">C.5.x Clause 15: Special member functions
[diff.cpp17.special]</SPAN></P>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">Affected subclauses: 15.1 [class.ctor],
15.4 [class.dtor]<BR>
Change: A <I>simple-template-id</I> is no longer valid as the
<I>declarator-id</I> of a constructor or destructor.<BR>
Rationale: Remove potentially error-prone option for redundancy.<BR>
Effect on original feature: Valid C++ 2017 code may fail to compile.</SPAN></P>

<PRE>
<SPAN style="font-weight:bold;background-color:#A0FFA0">  template&lt;class T&gt;
  struct A {
    A&lt;T&gt;();  //<SPAN style="font-family:Times;font-style:italic"> error: simple-template-id not allowed for constructor</SPAN>
    A(int);  //<SPAN style="font-family:Times;font-style:italic"> OK, injected-class-name used</SPAN>
    ~A&lt;T&gt;(); //<SPAN style="font-family:Times;font-style:italic"> error: simple-template-id not allowed for destructor</SPAN>
  };</SPAN>
</PRE>

</BLOCKQUOTE>

</OL>

<P>(Note that this resolution is a change for C++20, NOT a defect report
against C++17 and earlier versions.)</P>

<BR><BR><HR><A NAME="2255"></A><H4>2255.
  
Instantiated static data member templates
</H4><B>Section: </B>17.8&#160; [temp.spec]
 &#160;&#160;&#160;

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

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

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


<P>The current wording does not state that a specialization of a static
data member template (17 [temp] paragraph 1) is a static
data member, which leaves the status of an example like the following
unclear (since 8.2.5 [expr.ref] bullet 4.1 is phrased in
terms of static data members):</P>

<PRE>
  template &lt;class T&gt; struct A {
    template &lt;class U&gt; static const U x = 1;
    static const int y = 2;
  };

  int main() {
    A&lt;int&gt; a;
    int y = a.y;         //<SPAN style="font-family:Times;font-style:italic"> OK</SPAN>
    int x = a.x&lt;int&gt;;    //<SPAN style="font-family:Times;font-style:italic"> ???</SPAN>
  }
</PRE>

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

<P>Change 17.8 [temp.spec] paragraph 2 as follows:</P>

<BLOCKQUOTE>

A function instantiated from a function template is called an instantiated
function. A class instantiated from a class template is called an
instantiated class. A member function, a member class, a member
enumeration, or a static data member of a class template instantiated from
the member definition of the class template is called, respectively, an
instantiated member function, member class, member enumeration, or static
data member. A member function instantiated from a member function template
is called an instantiated member function. A member class instantiated from
a member class template is called an instantiated member class. <SPAN style="font-weight:bold;background-color:#A0FFA0">A
variable instantiated from a variable template is called an instantiated
variable. A static data member instantiated from a static data member
template is called an instantiated static data member.</SPAN>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2260"></A><H4>2260.
  
Explicit specializations of deleted member functions
</H4><B>Section: </B>17.8.3&#160; [temp.expl.spec]
 &#160;&#160;&#160;

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

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

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




<P>Although the Standard allows for explicitly specializing a deleted
function template, member function of a class template, or member
function template with a non-deleted definition, this seems to be
problematic for non-template member functions of class templates. For
example:</P>

<PRE>
  template&lt;typename T&gt; struct A { 
    A(const A&amp;) = delete; 
    A(A&amp;&amp;) = default; 
  }; 
  static_assert(is_trivially_copyable(A&lt;int&gt;)); 
  template&lt;&gt; struct A&lt;int&gt;::A(const A&amp;) { /* ... */ } 
  static_assert(is_trivially_copyable(A&lt;int&gt;)); 
  template&lt;typename T&gt; struct B { 
    virtual void f() = delete; 
  }; 
  struct C : B&lt;int&gt; { void f() override = delete; }; //<SPAN style="font-family:Times;font-style:italic"> ok, overriding deleted with deleted </SPAN>
  template&lt;&gt; void B&lt;int&gt;::f() {} //<SPAN style="font-family:Times;font-style:italic"> would make </SPAN>C<SPAN style="font-family:Times;font-style:italic"> retroactively ill-formed? </SPAN>
</PRE>

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

<P><TT>=delete</TT> definitions of member functions should be instantiated
when instantiating a class template. That would make the example an
ill-formed redefinition.</P>

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

<P>Change 17.8.1 [temp.inst] paragraph 2, breaking the running
text into bullets, as follows:</P>

<BLOCKQUOTE>

<P>The implicit instantiation of a class template specialization causes</P>

<UL><LI><P>the implicit instantiation of the declarations, but not of the
definitions, <SPAN style="text-decoration:line-through;background-color:#FFA0A0">default arguments, or <I>noexcept-specifier</I>s</SPAN> of
the <SPAN style="font-weight:bold;background-color:#A0FFA0">non-deleted</SPAN> class member functions, member classes, scoped
member enumerations, static data members, member templates, and friends;
and</P></LI>

<LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">it causes</SPAN> the implicit instantiation of the definitions
of <SPAN style="font-weight:bold;background-color:#A0FFA0">deleted member functions,</SPAN> unscoped member
enumerations<SPAN style="font-weight:bold;background-color:#A0FFA0">,</SPAN> and member anonymous unions.</P></LI>

</UL>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">The implicit instantiation of a class template specialization does not cause the implicit instantiation of default arguments or <I>noexcept-specifier</I>s of the class member functions. [<I>Example:</I></SPAN></P>

<PRE>
<SPAN style="font-weight:bold;background-color:#A0FFA0">  template&lt;class T&gt;
  struct C {
    void f() { T x; }
    void g() = delete;
  };
  C&lt;void&gt; c;                       //<SPAN style="font-family:Times;font-style:italic"> OK, definition of </SPAN>C&lt;void&gt;::f<SPAN style="font-family:Times;font-style:italic"> is not instantiated at this point</SPAN>
  template&lt;&gt; void C&lt;int&gt;::g() { }  //<SPAN style="font-family:Times;font-style:italic"> error: redefinition of </SPAN>C&lt;int&gt;::g</SPAN>
</PRE>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">&#8212;<I>end example</I>]</SPAN> However, for the purpose of
determining whether an instantiated redeclaration is valid according to
6.2 [basic.def.odr] and 12.2 [class.mem], a declaration that
corresponds to a definition in the template is considered to be a
definition.  [<I>Example:</I></P>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2299"></A><H4>2299.
  
<TT>constexpr</TT> vararg functions
</H4><B>Section: </B>10.1.5&#160; [dcl.constexpr]
 &#160;&#160;&#160;

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

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

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


<P>It is not clear whether a <TT>constexpr</TT> function can be a vararg
function or not. In particular, it is unclear if <TT>va_list</TT> is a
literal type and whether <TT>va_start</TT>, <TT>va_arg</TT>, and
<TT>va_end</TT> produce constant expressions.</P>

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

<OL><LI><P>Add a new bullet to the list in 8.20 [expr.const]
paragraph 2, and update the text as follows:</P></LI>

<BLOCKQUOTE>

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

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

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

<LI><P>a <I>throw-expression</I> (8.17 [expr.throw])<SPAN style="text-decoration:line-through;background-color:#FFA0A0">.</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">; or</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">an invocation of the <TT>va_arg</TT> macro
(21.10.1 [cstdarg.syn]).</SPAN></P></LI>

</UL>

<P>If <TT>e</TT> satisfies the constraints of a core constant expression,
but evaluation of <TT>e</TT> would evaluate an operation that has undefined
behavior as specified in Clause 20 [library] through Clause
33 [thread] of this document, <SPAN style="font-weight:bold;background-color:#A0FFA0">or an invocation of the
<TT>va_start</TT> macro (21.10.1 [cstdarg.syn]),</SPAN> it is
unspecified whether <TT>e</TT> is a core constant expression.</P>

</BLOCKQUOTE>

</OL>

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