C++ Logo


Advanced search

Re: [over.ics.rank] standard conversion tie-breakers from different source types

From: Edward Catmur <ecatmur_at_[hidden]>
Date: Tue, 10 Jan 2023 13:41:45 +0000
On Mon, 9 Jan 2023 at 23:04, Lénárd Szolnoki via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> Hi,
> I would like an example of a function call to an overloaded function,
> where the most viable function is determined by the rules listed from
> [over.ics.rank]/4.4.5 to [over.ics.rank]/4.4.8:
> https://timsong-cpp.github.io/cppwp/n4868/over.ics.rank#4.4.5
> These are four different tie-breakers for ranking standard conversions
> from different source types, assuming the following class hierarchy:
> struct A {}; struct B : C {}; struct C : B {};
> (4.4.5) conversion of B* to A* is better than conversion of C* to A*,
> (4.4.6) binding of an expression of type B to a reference to type A is
> better than binding an expression of type C to a reference to type A,
> (4.4.7) conversion of B::* to C::* is better than conversion of
> A::* to C::*, and
> (4.4.8) conversion of B to A is better than conversion of C to A.
> The note says that these are only used for tie-breakers in the second
> conversion sequence of user-defined conversions:
> https://timsong-cpp.github.io/cppwp/n4868/over.ics.rank#note-1
> However if two user-defined conversions yield different types before
> the second conversion sequence, then they are necessarily have to use
> different user-defined conversion functions or constructors, so the
> conversion sequences would be indistinguishable by [over.ics.rank]/3,
> as [over.ics.rank]/3.3 does not apply:
> https://timsong-cpp.github.io/cppwp/n4868/over.ics.rank#3.3

This appears to be defective. There is full agreement that the following
conversion is unambiguous:

struct A {};
struct B : A {};
struct C : B {};
struct X {
    operator B*();
    operator C*();
int f(A*);
int i = f(X()); // calls X::operator B*()

Likewise for the following 3 bullets of [over.ics.rank], and indeed in
general (e.g. X->float->double vs. X->int->double).
>From https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#2524 it
appears clear that X::operator B*() and X::operator C*() above are indeed
considered not to be the same user-defined conversion.
Please consider filing a DR.

Note: while I appreciate that you value referring to a specific draft
version, it would probably be better to refer to the numbering in the
current draft, viz. https://wg21.link/over.ics.rank#4.5.5 etc.

Having said that I have no idea what "or they initialize the same
> class in an aggregate initialization" means here, maybe that's the key.

It has to mean [over.ics.list], but every user-defined conversion specified
for aggregate initialization there is immediately followed by an identity
conversion, so that text appears to be ineffectual. Possibly a separate DR
would be a good idea.

Received on 2023-01-10 13:42:00