C++ Logo

std-discussion

Advanced search

Re: Implicit conversion sequence from literal 0

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Sun, 8 Jan 2023 11:18:36 +0000
On Sun, 8 Jan 2023 03:02:14 +0100
Phil via Std-Discussion <std-discussion_at_[hidden]> wrote:

> The example code favors the first overload because the 2nd argument
> (integer literal -> int -> Identity -> Exact Match) does not need to
> get narrowed to short like needed for the second overload (Integral
> conversions -> Conversion), i.e. it has a better rank.
>
> If you explicitly cast the 2nd argument to short, the second overload
> gets selected because of identity match for 2nd parameter. There is
> of course no ambiguity because the first overload (with an int as
> second parameter) would require a integral promotion which has rank
> promotion, but the identity match with short is still better (exakt
> match).
>
> If you change the 2nd parameter for the second overload from short to
> int/long, you will get ambiguity, because the first argument is
> always ambiguous since converting 0 to short as well as converting 0
> to void* are conversions and have the same rank. It just depends on
> the second parameter.
>
> If all shorts would be changed to ints, the second overload would be
> selected, since it had two times identity -> exact match (for both
> parameters). If the first overload changed its second parameter from
> int to short, there would be ambiguity again, since the compiler can
> not tell which conversion is "better": converting the first argument
> to void* or the second to short (both have rank: Conversion).

The example is deliberately crafted this way, so when both functions
are viable, the one with the `void *` is chosen, as it's more viable. If
only `void foo(short, short)` were viable, then it would be chosen
instead.

I agree that *if* `void foo(void*, int)` is viable, then it is also the
most viable. The question is if `void foo(void*, int)` viable or not.

> Therefore I do not see that this is an issue or related to
> "null-pointers". Or do I miss the point for this discussion
> completely?

I think you do. The point is that according to the wording, the call
`foo(0, 1)` wouldn't find the function `void foo(void *, int)` viable
at all, even though `0` can be converted to `void *` in general, as
(quoting the standard) "implicit conversion sequences are concerned
only with the type, cv-qualification, and value category of the
argument...". In this case `void foo(short, short)` is the only viable
overload, so that function should be called.

Basically according to the current wording, the viable overloads are
resolved for `foo(0, 1)` the same way as for `foo(1, 1)`.

Cheers,
Lénárd

Received on 2023-01-08 11:18:46