<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;P0818R0</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Date:
     </TD>
<TD>
      &#160;2017-10-16</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:2014
     </TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Reply to:
     </TD>
<TD>
      &#160;William M. Miller
     </TD>
</TR>
<TR>
<TD></TD>
<TD>
      &#160;Edison Design Group, Inc.
     </TD>
</TR>
<TR>
<TD></TD>
<TD>
      &#160;<A HREF="mailto://wmm@edg.com">wmm@edg.com</A></TD>
</TR>
</TABLE><BR CLEAR="ALL"><BR><CENTER>
<H2>
     Core Language Working Group "tentatively ready" Issues
     for the
     November, 2017 (Albuquerque) 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/n4659.pdf">WG21 N4659</A>.
   </P>
<HR><A NAME="2305"></A><H4>2305.
  
Explicit instantiation of constexpr or inline variable template
</H4><B>Section: </B>17.7.2&#160; [temp.explicit]
 &#160;&#160;&#160;

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

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

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


<P>According to 17.7.2 [temp.explicit] paragraph 1,</P>

<BLOCKQUOTE>

An explicit instantiation of a function template or member function of a
class template shall not use the <TT>inline</TT> or <TT>constexpr</TT>
specifiers.

</BLOCKQUOTE>

<P>Should this apply to explicit specializations of variable templates
as well?</P>

<P>(See also issues 1704 and
1728).</P>

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

<P>Change 17.7.2 [temp.explicit] paragraph 1 as follows:</P>

<BLOCKQUOTE>

A class, function, variable, or member template specialization can be
explicitly instantiated from its template.  A member function, member class
or static data member of a class template can be explicitly instantiated
from the member definition associated with its class template. An explicit
instantiation of a function template<SPAN style="text-decoration:line-through;background-color:#FFA0A0"> or</SPAN><SPAN style="font-weight:bold;background-color:#A0FFA0">,</SPAN>
member function of a class template<SPAN style="font-weight:bold;background-color:#A0FFA0">, or variable template</SPAN>
shall not use the <TT>inline</TT> or <TT>constexpr</TT> specifiers.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2307"></A><H4>2307.
  
Unclear definition of &#8220;equivalent to a nontype template parameter&#8221;
</H4><B>Section: </B>17.6.2.1&#160; [temp.dep.type]
 &#160;&#160;&#160;

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

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

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




<P>The description of whether a template argument is equivalent to a
template parameter in 17.6.2.1 [temp.dep.type] paragraph 3 is
unclear as it applies to non-type template parameters:</P>

<BLOCKQUOTE>

A template argument that is equivalent to a template parameter (i.e., has
the same constant value or the same type as the template parameter) can be
used in place of that template parameter in a reference to the current
instantiation. In the case of a non-type template argument, the argument
must have been given the value of the template parameter and not an
expression in which the template parameter appears as a subexpression.

</BLOCKQUOTE>

<P>For example:</P>

<PRE>
  template&lt;int N&gt; struct A { 
    typedef int T[N]; 
    static const int AlsoN = N; 
    A&lt;AlsoN&gt;::T s; //<SPAN style="font-family:Times;font-style:italic"> #0, clearly supposed to be OK </SPAN>
    static const char K = N; 
    A&lt;K&gt;::T t;     //<SPAN style="font-family:Times;font-style:italic"> #1, OK? </SPAN>
    static const long L = N; 
    A&lt;L&gt;::T u;     //<SPAN style="font-family:Times;font-style:italic"> #2, OK? </SPAN>
    A&lt;(N)&gt;::T v;   //<SPAN style="font-family:Times;font-style:italic"> #3, OK? </SPAN>
    static const int M = (N); 
    A&lt;M&gt;::T w;     //<SPAN style="font-family:Times;font-style:italic"> #4, OK? </SPAN>
  }; 
</PRE>

<P>#1 narrows the template argument. This obviously should not be the
injected-class-name, because <TT>A&lt;257&gt;::T</TT> may well
be <TT>int[1]</TT> not <TT>int[257]</TT> .  However, the wording above
seems to treat it as the injected-class-name.</P>

<P>#2 is questionable: there is potentially a narrowing conversion here, but
it doesn't actually narrow any values for the original template parameter.</P>

<P>#3 is hard to decipher. On the one hand, this is an expression involving
the template parameter. On the other hand, a parenthesized expression is
specified as being equivalent to its contained expression.</P>

<P>#4 should presumably go the same way that #3 does.</P>

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

<P>Change 17.6.2.1 [temp.dep.type] paragraph 3 as follows:</P>

<BLOCKQUOTE>


<P>A template argument that is equivalent to a template
parameter <SPAN style="text-decoration:line-through;background-color:#FFA0A0">(i.e., has the same constant value or the same type as the
template parameter)</SPAN> can be used in place of that template parameter
in a reference to the current instantiation. <SPAN style="font-weight:bold;background-color:#A0FFA0">For a template
<I>type-parameter</I>, a template argument is equivalent to a template
parameter if it denotes the same type. For a non-type template parameter,
a template argument is equivalent to a template parameter if it is an
<I>identifier</I> that names a variable that is equivalent to the
template parameter. A variable is equivalent to a template parameter
if</SPAN></P>
<UL><LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">it has the same type as the template parameter (ignoring
cv-qualification) and</SPAN></P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">its initializer consists of a single <I>identifier</I> that
names the template parameter or, recursively, such a variable.</SPAN></P></LI>

</UL>

<P><SPAN style="font-weight:bold;background-color:#A0FFA0">[<I>Note:</I> Using a parenthesized variable name breaks the
equivalence. &#8212;<I>end note</I>]</SPAN>
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">In the case of a non-type
template argument, the argument must have been given the value of the
template parameter and not an expression in which the template parameter
appears as a subexpression.</SPAN> [<I>Example:</I></P>

<PRE>
  template &lt;class T&gt; class A {
    A* p1;                   //<SPAN style="font-family:Times;font-style:italic"> </SPAN>A<SPAN style="font-family:Times;font-style:italic"> is the current instantiation</SPAN>
    A&lt;T&gt;* p2;                //<SPAN style="font-family:Times;font-style:italic"> </SPAN>A&lt;T&gt;<SPAN style="font-family:Times;font-style:italic"> is the current instantiation</SPAN>
    A&lt;T*&gt; p3;                //<SPAN style="font-family:Times;font-style:italic"> </SPAN>A&lt;T*&gt;<SPAN style="font-family:Times;font-style:italic"> is not the current instantiation</SPAN>
    ::A&lt;T&gt;* p4;              //<SPAN style="font-family:Times;font-style:italic"> </SPAN>::A&lt;T&gt;<SPAN style="font-family:Times;font-style:italic"> is the current instantiation</SPAN>
    class B {
      B* p1;                 //<SPAN style="font-family:Times;font-style:italic"> </SPAN>B<SPAN style="font-family:Times;font-style:italic"> is the current instantiation</SPAN>
      A&lt;T&gt;::B* p2;           //<SPAN style="font-family:Times;font-style:italic"> </SPAN>A&lt;T&gt;::B<SPAN style="font-family:Times;font-style:italic"> is the current instantiation</SPAN>
      typename A&lt;T*&gt;::B* p3; //<SPAN style="font-family:Times;font-style:italic"> </SPAN>A&lt;T*&gt;::B<SPAN style="font-family:Times;font-style:italic"> is not the current instantiation</SPAN>
    };
  };

  template &lt;class T&gt; class A&lt;T*&gt; {
    A&lt;T*&gt;* p1;               //<SPAN style="font-family:Times;font-style:italic"> </SPAN>A&lt;T*&gt;<SPAN style="font-family:Times;font-style:italic"> is the current instantiation</SPAN>
    A&lt;T&gt;* p2;                //<SPAN style="font-family:Times;font-style:italic"> </SPAN>A&lt;T&gt;<SPAN style="font-family:Times;font-style:italic"> is not the current instantiation</SPAN>
  };

  template &lt;class T1, class T2, int I&gt; struct B {
    B&lt;T1, T2, I&gt;* b1;        //<SPAN style="font-family:Times;font-style:italic"> refers to the current instantiation</SPAN>
    B&lt;T2, T1, I&gt;* b2;        //<SPAN style="font-family:Times;font-style:italic"> not the current instantiation</SPAN>
    typedef T1 my_T1;
    static const int my_I = I;
    static const int my_I2 = I+0;
    static const int my_I3 = my_I;
<SPAN style="font-weight:bold;background-color:#A0FFA0">    static const long my_I4 = I;
    static const int my_I5 = (I);</SPAN>
    B&lt;my_T1, T2, my_I&gt;* b3;   //<SPAN style="font-family:Times;font-style:italic"> refers to the current instantiation</SPAN>
    B&lt;my_T1, T2, my_I2&gt;* b4;  //<SPAN style="font-family:Times;font-style:italic"> not the current instantiation</SPAN>
    B&lt;my_T1, T2, my_I3&gt;* b5;  //<SPAN style="font-family:Times;font-style:italic"> refers to the current instantiation</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">    B&lt;my_T1, T2, my_I4&gt;* b6;  //<SPAN style="font-family:Times;font-style:italic"> not the current instantiation</SPAN>
    B&lt;my_T1, T2, my_I5&gt;* b7;  //<SPAN style="font-family:Times;font-style:italic"> not the current instantiation</SPAN></SPAN>
  };
</PRE>

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

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2313"></A><H4>2313.
  
Redeclaration of structured binding reference variables
</H4><B>Section: </B>11.5&#160; [dcl.struct.bind]
 &#160;&#160;&#160;

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

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

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




<P>According to the current rules for structured binding declarations,
the user-defined case declares the bindings as variables of reference
type. This presumably makes an example like the following valid:</P>

<PRE>
   auto [a] = std::tuple&lt;int&gt;(0); 
   extern int &amp;&amp;a; //<SPAN style="font-family:Times;font-style:italic"> ok, redeclaration, could even be in a different TU </SPAN>
</PRE>

<P>This seems unreasonable, especially in light of the fact that it only
works for the user-defined case and not the built-in case (where the
bindings are not modeled as references).</P>

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

<P>Change 11.5 [dcl.struct.bind] paragraph 3 as follows:</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. The <I>unqualified-id</I> <TT>get</TT> is looked up in the
scope of <TT>E</TT> by class member access lookup
(6.4.5 [basic.lookup.classref]), and if that finds at least one declaration,
the initializer is <TT>e.get&lt;i&gt;()</TT>.  Otherwise, the initializer
is <TT>get&lt;i&gt;(e)</TT> where <TT>get</TT> is looked up in the associated
namespaces (6.4.2 [basic.lookup.argdep]). In either case,
<TT>get&lt;i&gt;</TT> is interpreted as a <I>template-id</I>. [<I>Note:</I>
Ordinary unqualified lookup (6.4.1 [basic.lookup.unqual]) is not performed.
&#8212;<I>end note</I>] In either case, <TT>e</TT> is an lvalue if the type
of the entity <TT>e</TT> is an lvalue reference and an xvalue
otherwise. Given the type <TT>T</TT><SUB><I>i</I></SUB> designated
by <TT>std::tuple_element&lt;i, E&gt;::type</TT> ,
<SPAN style="text-decoration:line-through;background-color:#FFA0A0">each <TT>v</TT><SUB><I>i</I></SUB> is a variable</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">variables are introduced with unique
names <TT>r</TT><SUB><I>i</I></SUB></SPAN> of type &#8220;reference
to <TT>T</TT><SUB><I>i</I></SUB> &#8221; initialized with the initializer
<SPAN style="font-weight:bold;background-color:#A0FFA0">(11.6.3 [dcl.init.ref])</SPAN>, where the reference is an lvalue
reference if the initializer is an lvalue and an rvalue reference
otherwise<SPAN style="font-weight:bold;background-color:#A0FFA0">. Each <TT>v</TT><SUB><I>i</I></SUB> is the name of an lvalue
of type <TT>T</TT><SUB><I>i</I></SUB> that refers to the object bound
to <TT>r</TT><SUB><I>i</I></SUB></SPAN>; the referenced type
is <TT>T</TT><SUB><I>i</I></SUB>.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2315"></A><H4>2315.
  
Whst is the &#8220;corresponding special member&#8221; of a variant member?
</H4><B>Section: </B>15.8&#160; [class.copy]
 &#160;&#160;&#160;

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

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

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




<P>According to 15.8.1 [class.copy.ctor] bullet 10.1,</P>

<BLOCKQUOTE>

<P>A defaulted copy/move constructor for a class <TT>X</TT> is defined as
deleted (11.4.3 [dcl.fct.def.delete]) if <TT>X</TT> has:</P>

<UL><LI><P>a variant member with a non-trivial corresponding constructor
and <TT>X</TT> is a union-like class,</P></LI>

</UL>

</BLOCKQUOTE>

<P>However, it is not clear from this specification how to handle an
example like:</P>

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

<P>since there is no corresponding special member in <TT>A</TT>.</P>

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

<P>Change 15.8.1 [class.copy.ctor] paragraph 10 as follows:</P>

<BLOCKQUOTE>

<P>An implicitly-declared copy/move constructor is an inline public member of
its class. A defaulted copy/move constructor for a class <TT>X</TT> is
defined as deleted (11.4.3 [dcl.fct.def.delete]) if <TT>X</TT> has:</P>

<UL><LI><P><SPAN style="text-decoration:line-through;background-color:#FFA0A0">a variant member with a non-trivial corresponding
constructor and <TT>X</TT> is a union-like class,</SPAN></P></LI>

<LI><P>a potentially constructed subobject type <TT>M</TT> (or array
thereof) that cannot be copied/moved because overload resolution
(16.3 [over.match]), as applied to find <TT>M</TT>'s corresponding
constructor, results in an ambiguity or a function that is deleted or
inaccessible from the defaulted constructor,</P></LI>

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">a variant member whose corresponding constructor as selected
by overload resolution is non-trivial,</SPAN></P></LI>

<LI><P>any potentially constructed subobject of a type with a destructor
that is deleted or inaccessible from the defaulted constructor,
or,</P></LI>

<LI><P>for the copy constructor, a non-static data member of rvalue
reference type.</P></LI>

</UL>

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2338"></A><H4>2338.
  
Undefined behavior converting to short enums with fixed underlying types
</H4><B>Section: </B>8.2.9&#160; [expr.static.cast]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2017-03-24


<P>The specifications of <TT>std::byte</TT>
(21.2.5 [support.types.byteops]) and <TT>bitmask</TT>
(20.4.2.1.4 [bitmask.types]) have revealed a problem with
the integral conversion rules, according to which both those
specifications have, in the general case. undefined behavior. The
problem is that a conversion to an enumeration type has undefined
behavior unless the value to be converted is in the range of the
enumeration.</P>

<P>For enumerations with an unsigned fixed underlying type, this
requirement is overly restrictive, since converting a large value
to an unsigned integer type is well-defined.</P>

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

<P>Change 8.2.9 [expr.static.cast] paragraph 10 as follows:</P>

<BLOCKQUOTE>

A value of integral or enumeration type can be explicitly
converted to a complete enumeration type. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">The</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">If
the enumeration type has a fixed underlying type, the value is
first converted to that type by integral conversion, if
necessary, and then to the enumeration type. If the enumeration
type does not have a fixed underlying type, the</SPAN> value is
unchanged if the original value is within the range of the
enumeration values
(10.2 [dcl.enum])<SPAN style="text-decoration:line-through;background-color:#FFA0A0">. Otherwise</SPAN><SPAN style="font-weight:bold;background-color:#A0FFA0">, and
otherwise</SPAN>, the behavior is undefined.

</BLOCKQUOTE>

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