Re: overload resolution and conversion ops
On 16 mai, 14:24, xtrigger...@gmail.com wrote:
I was reading Mr. Alexandrescu's mojo article and I've a hard
time understanding the following.
Let's suppose I have:
//code
struct A {};
struct B : A {};
struct C
{
operator A() const { return A(); }
operator B() { return B(); }
};
void F( A const & ) {}
void F( B const & ) {}
C const H() { return C(); }
int main()
{
F( C() ); // 1. called with a non-const rvalue
F( H() ); // 2. called with a const rvalue}
}
//end code
I understand that if I have a const "C" (rvalue or lvalue,
here it does not matter) the only option when calling "F"
would be to use
C::operator A() const -> F( A const & )
Correct. The C::operator B() conversion operator cannot be
called (is not a viable function, in the words of the standard).
In the case I have a non-const "C" it seems that the compiler
chooses
C::operator B() -> F( B const & )
my understanding of the article is that this is because since
B is derived from A, it's a better match than the base class.
I do not understand then why the constness of operator A()
makes the difference.
It's rather the non-const-ness of operator B() that makes the
difference. Because the operator is not const, it cannot be
called on a const object.
If I remove it and make it just
C::operator A()
my guess would be that that when calling "F" I would always
get a call to
F( B const & ). But instead the thing does not compile.
If the object is const, only const functions can be called on
it. If you remove const everywhere, then no functions can be
called on the object. Whence your error.
My naive understanding then is that the constness of the
conversion operators AND the fact the B is derived from A all
come into play when "resolving" the call to "F".
Sort of. Overload resolution doesn't consider functions which
cannot be called because of a mismatch in the signatures. (It
doesn't take things like access protection into consideration,
so overload resolution can resolve to a private function which
cannot be called.)
The problem is that I cannot fully understand the logic behind
this nor I can find the right chapter in the standard. Tryed
[over.ics.rank]. Any help to understand this better would be
greatly appreciated.
You're not looking far enough. In the terms of the standard,
overload resolution takes place in three steps: creating a list
of candidate functions (results of name lookup and possibly
template instantiations), creating a set of viable functions
from the candidate functions (only those candidate functions
whose signatures allow them to be called), and finally, choosing
the best candidate function. In more usual terminology, only
this last step would be considered "resolution", the first two
steps only construct the set over which resolution is applied.
But regardless of how they are called, all three steps take
place, and the compiler will not consider a function that it
doesn't find during name lookup (first step) or whose signature
will not allow it to be called (second step).
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34