<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;P0818R1</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Date:
     </TD>
<TD>
      &#160;2017-11-10</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/n4700.pdf">WG21 N4700</A>.
   </P>
<HR><A NAME="1862"></A><H4>1862.
  
Determining &#8220;corresponding members&#8221; for friendship
</H4><B>Section: </B>17.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>2014-02-13


<P>During the discussion of issue 1804, it was
noted that the process of determining whether a member of an explicit or
partial specialization corresponds to a member of the primary template is
not well specified.  In particular, it should be clarified that the primary
template should not be instantiated during this process; instead, the
template arguments from the specialization should simply be substituted
into the member declaration.</P>

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

<P>Change 17.6.4 [temp.friend] paragraph 4 as follows:</P>

<BLOCKQUOTE>

<P>A <SPAN style="font-weight:bold;background-color:#A0FFA0">template friend declaration may declare a</SPAN>
member of a <SPAN style="text-decoration:line-through;background-color:#FFA0A0">class template may be declared</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">dependent type</SPAN> to be a friend <SPAN style="text-decoration:line-through;background-color:#FFA0A0">of a
non-template class</SPAN>. <SPAN style="font-weight:bold;background-color:#A0FFA0">The friend declaration shall declare a
function or specify a type with an <I>elaborated-type-specifier</I>,
in either case with a <I>nested-name-specifier</I> ending with a
<I>simple-template-id</I>, <I>C</I>, whose <I>template-name</I> names
a class template. The template parameters of the template friend
declaration shall be deducible from <I>C</I>
(17.9.2.5 [temp.deduct.type]).</SPAN>
In this case, <SPAN style="text-decoration:line-through;background-color:#FFA0A0">the corresponding member of every
specialization of the primary class template and class template partial
specializations thereof</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">a member of a specialization
<I>S</I> of the class template</SPAN>
is a friend of the class granting friendship<SPAN style="text-decoration:line-through;background-color:#FFA0A0">. For
explicit specializations and specializations of partial specializations,
the corresponding member is the member (if any) that has the same name,
kind (type, function, class template, or function template), template
parameters, and signature as the member of the class template instantiation
that would otherwise have been generated</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">if deduction of the template parameters of <I>C</I> from <I>S</I>
succeeds, and substituting the deduced template arguments into the
friend declaration produces a declaration that would be a valid
redeclaration of the member of the specialization</SPAN>. [<I>Example:</I></P>

<PRE>
  template&lt;class T&gt; struct A {
    struct B { };
    void f();
    struct D {
      void g();
    };
<SPAN style="font-weight:bold;background-color:#A0FFA0">    T h();
    template&lt;T U&gt; T i();</SPAN>
  };
  template&lt;&gt; struct A&lt;int&gt; {
    struct B { };
    int f();
    struct D {
      void g();
    };
<SPAN style="font-weight:bold;background-color:#A0FFA0">    template&lt;int U&gt; int i();</SPAN>
  };
<SPAN style="font-weight:bold;background-color:#A0FFA0">  template&lt;&gt; struct A&lt;float*&gt; {
    int *h();
  };</SPAN>
  class C {
    template&lt;class T&gt; friend struct A&lt;T&gt;::B;      //<SPAN style="font-family:Times;font-style:italic"> grants friendship to </SPAN>A&lt;int&gt;::B<SPAN style="font-family:Times;font-style:italic"> even though</SPAN>
                                                  //<SPAN style="font-family:Times;font-style:italic"> it is not a specialization of </SPAN>A&lt;T&gt;::B
    template&lt;class T&gt; friend void A&lt;T&gt;::f();      //<SPAN style="font-family:Times;font-style:italic"> does not grant friendship to </SPAN>A&lt;int&gt;::f()
                                                  //<SPAN style="font-family:Times;font-style:italic"> because its return type does not match</SPAN>
    template&lt;class T&gt; friend void A&lt;T&gt;::D::g();   //<SPAN style="text-decoration:line-through;background-color:#FFA0A0"><SPAN style="font-family:Times;font-style:italic"> does not grant friendship to </SPAN>A&lt;int&gt;::D::g()
                                                  //<SPAN style="font-family:Times;font-style:italic"> because </SPAN>A&lt;int&gt;::D<SPAN style="font-family:Times;font-style:italic"> is not a specialization of </SPAN>A&lt;T&gt;::D</SPAN><SPAN style="font-weight:bold;background-color:#A0FFA0"><SPAN style="font-family:Times;font-style:italic"> ill-formed, </SPAN>A&lt;T&gt;::D<SPAN style="font-family:Times;font-style:italic"> does not end with a simple-template-id</SPAN></SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">    template&lt;class T&gt; friend int *A&lt;T*&gt;::h();     //<SPAN style="font-family:Times;font-style:italic"> grants friendship to </SPAN>A&lt;int*&gt;::h()<SPAN style="font-family:Times;font-style:italic"> and </SPAN>A&lt;float*&gt;::h()
    template&lt;class T&gt; template&lt;T U&gt;               //<SPAN style="font-family:Times;font-style:italic"> grants friendship to instantiations of </SPAN>A&lt;T&gt;::i()<SPAN style="font-family:Times;font-style:italic"> and to </SPAN>A&lt;int&gt;::i()
      friend T A&lt;T&gt;::i();                         //<SPAN style="font-family:Times;font-style:italic"> and thereby to all specializations of those function templates</SPAN></SPAN>
  };
</PRE>

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

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2177"></A><H4>2177.
  
Placement <TT>operator delete</TT> and parameter copies
</H4><B>Section: </B>8.3.4&#160; [expr.new]
 &#160;&#160;&#160;

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

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

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




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

<PRE>
  void *operator new(size_t n, std::string s) {
    std::string t = std::move(s);
    std::cout &lt;&lt; "new " &lt;&lt; t &lt;&lt; std::endl;
    return operator new(n);
  }
  void operator delete(void*, std::string s) {
    std::cout &lt;&lt; "delete " &lt;&lt; s &lt;&lt; std::endl;
  }
  struct X { X() { throw 0; } };
  int main() {
    try {
      new ("longer than the small string buffer") X();
    } catch (...) {}
  }
</PRE>

<P>Current implementations print</P>

<PRE>
  new longer than the small string buffer
  delete
</PRE>

<P>because  the same <TT>std::string</TT> object is used for
both the new and delete calls.  We should introduce additional
copies to separate out the parameters in this case or make
non-trivially-copyable parameter types ill-formed here.</P>

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

<P>CWG favored limiting the parameters of an overloaded
deallocation function to trivially-copyable types.</P>

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

<P>Change 8.3.4 [expr.new] paragraph 24 as follows:</P>

<BLOCKQUOTE>

If a <I>new-expression</I> calls a deallocation function, it passes the
value returned from the allocation function call as the first argument of
type <TT>void*</TT>. If a placement deallocation function is called, it is
passed the same additional arguments as were passed to the placement
allocation function, that is, the same arguments as those specified with
the <I>new-placement</I> syntax. If the implementation is allowed
to <SPAN style="font-weight:bold;background-color:#A0FFA0">introduce a temporary object or</SPAN> make a copy of any argument
as part of the call to the allocation function, it is <SPAN style="text-decoration:line-through;background-color:#FFA0A0">allowed to make
a copy (of the same original value) as part of the call to the deallocation
function or to reuse the copy made as part of the call to the allocation
function. If the copy is elided in one place, it need not be elided in the
other</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">unspecified whether the same object is used in the call to
both the allocation and deallocation functions</SPAN>,

</BLOCKQUOTE>

<BR><BR><HR><A NAME="2305"></A><H4>2305.
  
Explicit instantiation of constexpr or inline variable template
</H4><B>Section: </B>17.8.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.8.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.8.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.7.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.7.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.7.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>

<P><B>Additional note (November, 2017):</B></P>

<P>It was observed that the proposed resolution does not address partial
specializations, which also depend on the definition of equivalence.
 For example:</P>

<PRE>
  template &lt;typename T, unsigned N&gt; struct A; 
  template &lt;typename T&gt; struct A&lt;T, 42u&gt; { 
    typedef int Ty; 
    static const unsigned num = 42u; 
    static_assert(!A&lt;T, num&gt;::Ty(), ""); 
  }; 
  A&lt;int, 42u&gt; a; //<SPAN style="font-family:Times;font-style:italic"> GCC, MSVC, ICC accepts; Clang rejects </SPAN>
</PRE>

<P>The issue is being returned to "review" status in order to consider
these additional questions.</P>

<P><B>Notes from the November, 2017 (Albuquerque) meeting:</B></P>

<P>CWG decided to proceed with this resolution and deal with
partial specialization in a separate issue.</P>

<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>
