<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;P1350R0</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Date:
     </TD>
<TD>
      &#160;2018-11-07</TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Project:
     </TD>
<TD>
      &#160;Programming Language C++
     </TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Reference:
     </TD>
<TD>
      &#160;ISO/IEC IS 14882:2017
     </TD>
</TR>
<TR>
<TD ALIGN="RIGHT">
      Reply to:
     </TD>
<TD>
      &#160;William M. Miller
     </TD>
</TR>
<TR>
<TD></TD>
<TD>
      &#160;Edison Design Group, Inc.
     </TD>
</TR>
<TR>
<TD></TD>
<TD>
      &#160;<A HREF="mailto://wmm@edg.com">wmm@edg.com</A></TD>
</TR>
</TABLE><BR CLEAR="ALL"><BR><CENTER>
<H2>
     Core Language Working Group "tentatively ready" Issues
     for the
     November, 2018 (San Diego) 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/2018/n4778.pdf">WG21 N4778</A>.
   </P>
<HR><A NAME="1636"></A><H4>1636.
  
Bits required for negative enumerator values
</H4><B>Section: </B>9.6&#160; [dcl.enum]
 &#160;&#160;&#160;

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

 <B>Submitter: </B>Hyman Rosen
 &#160;&#160;&#160;

 <B>Date: </B>2013-03-07


<P>According to 9.6 [dcl.enum] paragraph 7,</P>

<BLOCKQUOTE>

For an enumeration whose underlying type is fixed, the values of the
enumeration are the values of the underlying type.  Otherwise,
for an enumeration where <I>e<SUB>min</SUB></I> is the smallest
enumerator and <I>e<SUB>max</SUB></I> is the largest, the values of
the enumeration are the values in the range <I>b<SUB>min</SUB></I> to
<I>b<SUB>max</SUB></I>, defined as follows: Let <I>K</I> be 1 for a
two's complement representation and 0 for a one's complement or
sign-magnitude representation.  <I>b<SUB>max</SUB></I> is the smallest
value greater than or equal to
max(|<I>e<SUB>min</SUB></I>|-<I>K</I>,|<I>e<SUB>max</SUB></I>|) and
equal to 2<I><SUP>M</SUP></I>-1, where <I>M</I> is a non-negative
integer.  <I>b<SUB>min</SUB></I> is zero if <I>e<SUB>min</SUB></I> is
non-negative and -(<I>b<SUB>max</SUB></I>+<I>K</I>) otherwise.  The
size of the smallest bit-field large enough to hold all the values of
the enumeration type is max(<I>M</I>,1) if <I>b<SUB>min</SUB></I> is
zero and <I>M</I>+1 otherwise.

</BLOCKQUOTE>

<P>The result of these calculations is that the number of bits
required for</P>

<PRE>
  enum { N = -1, Z = 0 }
</PRE>

<P>is 1, but the number required for</P>

<PRE>
  enum { N = -1 }
</PRE>

<P>is 2.  This is surprising.  This could be fixed by changing
|<I>e<SUB>max</SUB></I>| to <I>e<SUB>max</SUB></I>.</P>

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

<P>Change 9.6 [dcl.enum] paragraph 8 as follows:</P>

<BLOCKQUOTE>

<I>b</I><SUB>max</SUB> is the smallest value greater than or
equal to <I>max</I>(|<I>e</I><SUB>min</SUB>| - <I>K</I><SPAN style="text-decoration:line-through;background-color:#FFA0A0">,
|<I>e</I><SUB>max</SUB>|)</SPAN>
<SPAN style="font-weight:bold;background-color:#A0FFA0">, <I>e</I><SUB>max</SUB>)</SPAN> and equal to
2<SUP><I>M</I></SUP> - 1, where <I>M</I> is a non-negative
integer.

</BLOCKQUOTE>

<BR><BR><HR><A NAME="1781"></A><H4>1781.
  
Converting from <TT>nullptr_t</TT> to <TT>bool</TT> in overload resolution
</H4><B>Section: </B>11.3.1.5&#160; [over.match.conv]
 &#160;&#160;&#160;

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

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

 <B>Date: </B>2013-09-26


<P>According to 11.3.1.5 [over.match.conv] paragraph 1, when a class
type <TT>S</TT> is used as an initializer for an object of type <TT>T</TT>,
</P>

<BLOCKQUOTE>

The conversion functions of <TT>S</TT> and its base classes are
considered. Those non-explicit conversion functions that are not hidden
within <TT>S</TT> and yield type <TT>T</TT> or a type that can be converted
to type <TT>T</TT> via a standard conversion sequence
(11.3.3.1.1 [over.ics.scs]) are candidate functions.

</BLOCKQUOTE>

<P>Because conversion from <TT>std::nullptr_t</TT> to <TT>bool</TT>
is only permitted in direct-initialization (7.3.13 [conv.fctptr]),
it is not clear whether there is a standard conversion sequence from
<TT>std::nullptr_t</TT> to <TT>bool</TT>, considering that an
implicit conversion sequence is intended to model
copy-initialization.  Should 11.3.1.5 [over.match.conv] be
understood to refer only to conversions permitted in
copy-initialization, or should the form of the initialization be
considered?  For example,</P>

<PRE>
  struct SomeType {
    operator std::nullptr_t();
  };
  bool b{ SomeType() };    //<SPAN style="font-family:Times;font-style:italic"> Well-formed?</SPAN>
</PRE>

<P>Note also 11.3.3.2 [over.ics.rank] paragraph 4, which may bear
on the intent (or, alternatively, might describe a situation that
cannot arise):</P>

<BLOCKQUOTE>

A conversion that does not convert a pointer, a pointer to member, or
<TT>std::nullptr_t</TT> to <TT>bool</TT> is better than one that does.

</BLOCKQUOTE>

<P>See also issues 2133 and
2243.)</P>

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

<OL><LI><P>Change 7.3.14 [conv.bool] paragraph 1 as follows:</P></LI>

<BLOCKQUOTE>

A prvalue of arithmetic, unscoped enumeration, pointer, or
pointer-to-member type can be converted to a prvalue of type
<TT>bool</TT>. A zero value, null pointer value, or null member
pointer value is converted to <TT>false</TT>; any other value is
converted to <TT>true</TT>. <SPAN style="text-decoration:line-through;background-color:#FFA0A0">For direct-initialization
(9.3 [dcl.init]), a prvalue of type
<TT>std::nullptr_t</TT> can be converted to a prvalue of
type <TT>bool</TT>; the resulting value is <TT>false</TT>.</SPAN>

</BLOCKQUOTE>

<LI><P>Add the following bullet before 9.3 [dcl.init]
bullet 17.8:</P></LI>

<BLOCKQUOTE>

<P>The semantics of initializers are as follows. The
<I>destination type</I> is the type of the object or
reference being initialized and the <I>source type</I> is
the type of the initializer expression. If the initializer
is not a single (possibly parenthesized) expression, the
source type is not defined.</P>

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

<LI><P><SPAN style="font-weight:bold;background-color:#A0FFA0">Otherwise, if the initialization is
direct-initialization, the source type
is <TT>std::nullptr_t</TT>, and the destination type
is <TT>bool</TT>, the initial value of the object being
initialized is <TT>false</TT>.</SPAN></P></LI>

<LI><P>Otherwise, the initial value of the object being
initialized is the (possibly converted) value...</P></LI>

</UL>

</BLOCKQUOTE>

<LI><P>Change 11.3.3.2 [over.ics.rank] bullet 4.1 as follows:</P></LI>

<BLOCKQUOTE>

<P>Standard conversion sequences are ordered by their ranks: an
Exact Match is a better conversion than a Promotion, which
is a better conversion than a Conversion. Two conversion
sequences with the same rank are indistinguishable unless
one of the following rules applies:</P>

<UL><LI><P>A conversion that does not convert a
pointer<SPAN style="text-decoration:line-through;background-color:#FFA0A0">,</SPAN> <SPAN style="font-weight:bold;background-color:#A0FFA0">or</SPAN> a pointer to member<SPAN style="text-decoration:line-through;background-color:#FFA0A0">,
or <TT>std::nullptr_t</TT></SPAN> to <TT>bool</TT> is better
than one that does.</P></LI>

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

</UL>

</BLOCKQUOTE>

</OL>

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

<BR><BR><HR><A NAME="2133"></A><H4>2133.
  
Converting <TT>std::nullptr_t</TT> to <TT>bool</TT>
</H4><B>Section: </B>7.3.13&#160; [conv.fctptr]
 &#160;&#160;&#160;

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

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

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




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

<BLOCKQUOTE>

For direct-initialization (9.3 [dcl.init]), a
prvalue of type <TT>std::nullptr_t</TT> can be converted to a prvalue
of type <TT>bool</TT>; the resulting value is <TT>false</TT>.

</BLOCKQUOTE>

<P>The mention of direct-initialization in this context (added by
issue 1423) seems odd; standard
conversions are on a level below initialization.  Should this
wording be moved to 9.3 [dcl.init], perhaps as a
bullet in paragraph 1?</P>

<P>(See also issue 1781.)</P>

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

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

<BR><BR><HR><A NAME="2373"></A><H4>2373.
  
Incorrect handling of static member function templates in partial ordering
</H4><B>Section: </B>12.6.6.2&#160; [temp.func.order]
 &#160;&#160;&#160;

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

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

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


<P>According to 12.6.6.2 [temp.func.order] paragraph 3,</P>

<BLOCKQUOTE>

...If only one of the function templates <I>M</I> is a
non-static member of some class <I>A</I>, <I>M</I> is
considered to have a new first parameter inserted in its
function parameter list. Given <I>cv</I> as the
cv-qualifiers of <I>M</I> (if any), the new parameter is of
type &#8220;rvalue reference to <I>cv A</I>&#8221; if the
optional <I>ref-qualifier</I> of <I>M</I> is &amp;&amp; or
if <I>M</I> has no <I>ref-qualifier</I> and the first
parameter of the other template has rvalue reference
type. Otherwise, the new parameter is of type &#8220;lvalue
reference to <I>cv A</I>&#8221;. [<I>Note:</I> This allows a
non-static member to be ordered with respect to a non-member
function and for the results to be equivalent to the
ordering of two equivalent non-members. &#8212;<I>end
note</I>]

</BLOCKQUOTE>

<P>This gives the wrong answer for an example like:</P>

<PRE>
  struct Foo {
    template &lt;typename T&gt;
    static T* f(Foo*) { return nullptr; }

    template &lt;typename T, typename A1&gt;
    T* f(const A1&amp;) { return nullptr; }
  };

  int main() {
    Foo x;
    x.f&lt;int&gt;(&amp;x);
  } 
</PRE>

<P>Presumably this should say something like,</P>

<BLOCKQUOTE>

...If only one of the function templates <I>M</I> is a member
function, and that function is a non-static member...

</BLOCKQUOTE>

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

<P>Change 12.6.6.2 [temp.func.order] paragraph 3 as follows:</P>

<BLOCKQUOTE>

...If only one of the function templates <I>M</I> is a
<SPAN style="font-weight:bold;background-color:#A0FFA0">member function, and that function is a</SPAN>
non-static member of some class <I>A</I>, <I>M</I> is
considered to have a new first parameter inserted in its
function parameter list. Given <I>cv</I> as the
cv-qualifiers of <I>M</I> (if any), the new parameter is of
type &#8220;rvalue reference to <I>cv A</I>&#8221; if the
optional <I>ref-qualifier</I> of <I>M</I> is &amp;&amp; or
if <I>M</I> has no <I>ref-qualifier</I> and the first
parameter of the other template has rvalue reference
type. Otherwise, the new parameter is of type &#8220;lvalue
reference to <I>cv A</I>&#8221;. [<I>Note:</I> This allows a
non-static member to be ordered with respect to a non-member
function and for the results to be equivalent to the
ordering of two equivalent non-members. &#8212;<I>end
note</I>]

</BLOCKQUOTE>

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