Document number: | P1350R0 |

Date: | 2018-11-07 |

Project: | Programming Language C++ |

Reference: | ISO/IEC IS 14882:2017 |

Reply to: | William M. Miller |

Edison Design Group, Inc. | |

wmm@edg.com |

Section references in this document reflect the section numbering of document WG21 N4778.

According to 9.6 [dcl.enum] paragraph 7,

For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, for an enumeration whereeis the smallest enumerator and_{min}eis the largest, the values of the enumeration are the values in the range_{max}bto_{min}b, defined as follows: Let_{max}Kbe 1 for a two's complement representation and 0 for a one's complement or sign-magnitude representation.bis the smallest value greater than or equal to max(|_{max}e|-_{min}K,|e|) and equal to 2_{max}-1, where^{M}Mis a non-negative integer.bis zero if_{min}eis non-negative and -(_{min}b+_{max}K) otherwise. The size of the smallest bit-field large enough to hold all the values of the enumeration type is max(M,1) ifbis zero and_{min}M+1 otherwise.

The result of these calculations is that the number of bits required for

enum { N = -1, Z = 0 }

is 1, but the number required for

enum { N = -1 }

is 2. This is surprising. This could be fixed by changing
|*e _{max}*| to

**Proposed resolution (June, 2018):**

Change 9.6 [dcl.enum] paragraph 8 as follows:

b_{max}is the smallest value greater than or equal tomax(|e_{min}| -K, |e_{max}|) ,e_{max}) and equal to 2^{M}- 1, whereMis a non-negative integer.

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

The conversion functions ofSand its base classes are considered. Those non-explicit conversion functions that are not hidden withinSand yield typeTor a type that can be converted to typeTvia a standard conversion sequence (11.3.3.1.1 [over.ics.scs]) are candidate functions.

Because conversion from `std::nullptr_t` to `bool`
is only permitted in direct-initialization (7.3.13 [conv.fctptr]),
it is not clear whether there is a standard conversion sequence from
`std::nullptr_t` to `bool`, 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,

```
struct SomeType {
operator std::nullptr_t();
};
bool b{ SomeType() }; // Well-formed?
```

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

A conversion that does not convert a pointer, a pointer to member, orstd::nullptr_ttoboolis better than one that does.

See also issues 2133 and 2243.)

**Proposed resolution (June, 2018):**

Change 7.3.14 [conv.bool] paragraph 1 as follows:

Add the following bullet before 9.3 [dcl.init] bullet 17.8:

...

Otherwise, if the initialization is direct-initialization, the source type is

`std::nullptr_t`, and the destination type is`bool`, the initial value of the object being initialized is`false`.Otherwise, the initial value of the object being initialized is the (possibly converted) value...

Change 11.3.3.2 [over.ics.rank] bullet 4.1 as follows:

A conversion that does not convert a pointer, or a pointer to member, or

`std::nullptr_t`to`bool`is better than one that does....

A prvalue of arithmetic, unscoped enumeration, pointer, or pointer-to-member type can be converted to a prvalue of typebool. A zero value, null pointer value, or null member pointer value is converted tofalse; any other value is converted totrue. For direct-initialization (9.3 [dcl.init]), a prvalue of typestd::nullptr_tcan be converted to a prvalue of typebool; the resulting value isfalse.

The semantics of initializers are as follows. The

destination typeis the type of the object or reference being initialized and thesource typeis the type of the initializer expression. If the initializer is not a single (possibly parenthesized) expression, the source type is not defined.

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:

This resolution also resolves issue 2133.

According to 7.3.13 [conv.fctptr] paragraph 1,

For direct-initialization (9.3 [dcl.init]), a prvalue of typestd::nullptr_tcan be converted to a prvalue of typebool; the resulting value isfalse.

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?

(See also issue 1781.)

**Proposed resolution (June, 2018):**

This issue is resolved by the resolution of issue 1781.

According to 12.6.6.2 [temp.func.order] paragraph 3,

...If only one of the function templatesMis a non-static member of some classA,Mis considered to have a new first parameter inserted in its function parameter list. Givencvas the cv-qualifiers ofM(if any), the new parameter is of type “rvalue reference tocv A” if the optionalref-qualifierofMis && or ifMhas noref-qualifierand the first parameter of the other template has rvalue reference type. Otherwise, the new parameter is of type “lvalue reference tocv A”. [Note: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. —end note]

This gives the wrong answer for an example like:

struct Foo { template <typename T> static T* f(Foo*) { return nullptr; } template <typename T, typename A1> T* f(const A1&) { return nullptr; } }; int main() { Foo x; x.f<int>(&x); }

Presumably this should say something like,

...If only one of the function templatesMis a member function, and that function is a non-static member...

**Proposed resolution (October, 2018):**

Change 12.6.6.2 [temp.func.order] paragraph 3 as follows:

...If only one of the function templatesMis a member function, and that function is a non-static member of some classA,Mis considered to have a new first parameter inserted in its function parameter list. Givencvas the cv-qualifiers ofM(if any), the new parameter is of type “rvalue reference tocv A” if the optionalref-qualifierofMis && or ifMhas noref-qualifierand the first parameter of the other template has rvalue reference type. Otherwise, the new parameter is of type “lvalue reference tocv A”. [Note: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. —end note]