- [..]
- (4.3) If class B is derived directly or indirectly from class A, conversion of B* to A* is better than conversion of B* to void*, and conversion of A* to void* is better than conversion of B* to void*.
So if I have:
struct A {};
struct M : A {};
struct B : M {};
void f(A*);
void f(void*);
int main()
{
B *bptr = new B();
f(bptr);
}
The call f(bptr)
would prefer the overload f(A*)
over f(void*)
.
But in the second case: conversion of A* to void* is better than conversion of B* to void*. How this conversion can occur? Can you give me an example that triggers this case?
For some reasons I can't finds out a case or an example in which this case is applied. It seems like comparing two unrelated things to each other. But I encounter more in the bullet 4.4.
You can check the whole thing from cppreference para 4:
- If Mid is derived (directly or indirectly) from Base, and Derived is derived (directly or indirectly) from Mid
- a) Derived* to Mid* is better than Derived* to Base*
- b) Derived to Mid& or Mid&& is better than Derived to Base& or Base&&
- c) Base::* to Mid::* is better than Base::* to Derived::*
- d) Derived to Mid is better than Derived to Base
- e) Mid* to Base* is better than Derived* to Base*
- f) Mid to Base& or Base&& is better than Derived to Base& or Base&&
- g) Mid::* to Derived::* is better than Base::* to Derived::*
- h) Mid to Base is better than Derived to Base
CodePudding user response:
The situation where you have to compare different possible source types (A*
vs B*
in A* -> void*
and B* -> void*
) can only happen in the context of overload resolution for initialization by user-defined conversion, not in the context of overload resolution for a function call. See also the note at the end of [over.ics.rank]/4.
Here is an example where the quoted phrase is relevant:
struct A {};
struct B : A {};
struct C {
operator A*();
operator B*();
};
int main() {
void* x = C{};
}
Here x
is initialized by a conversion function chosen according to [over.match.conv] (see [dcl.init.general]/16.7). All conversion operators converting from C
to any type which is convertible to void*
by a standard conversion sequence are considered.
Then the best conversion function is chosen according to which of the standard conversion sequences following the conversion function is better (see [over.match.best.general]/2.2).
The phrase you quote tells us that A* -> void*
is better than B* -> void*
. So the conversion function which will be used here to initialize x
is operator A*()
.