473,385 Members | 1,720 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

overload resolution and conversion ops

Hi to all,
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 & )
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. 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.

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". 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.

Thanks in advance,
Francesco
Jun 27 '08 #1
2 1841
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:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Jun 27 '08 #2
James Kanze wrote:
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).

Thanks for the answer Mr. Kanze.
What happens when the object is const is clear.
What I don't get is what happens when the object is non-const.
Let's suppose I have this:

// 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 & ) { }

int main()
{
F( C() );
}
// end code

The above compiles, but if I remove just ONE of the two conditions:
- B being derived from A, OR
- op B() being non-const
The code becomes ambiguous.

So my understanding is that:

- first the compiler chooses the viable functions and in the above case
it seems that both op A() and op B() are viable because they can BOTH be
called on non-const object.

- in some way the compiler "prefers" the non-const version because I'm
calling F with a non-const object. BUT this is not enough because if at
this point B were not derived from A the code would not work.

- the fact that B is derived from A makes the compiler finally decides
that op B() is the best match. Note that this condition alone would not
be enough, if for example both op A() and OP B() were const.

So what I'm puzzled about is that these two conditions seem to sum up
the "viability" of the functions (I'm using layman terms here, sorry...)
They're not sufficient alone but combined they work.
I had a (quick) read through all [over.match] but could not really grasp
how this particular thing works...
Thanks again,
Francesco
Jun 27 '08 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Richard Hayden | last post by:
Hi, I have the following code for example: /**********************************/ #include <iostream> class C1 { public:
0
by: Eph0nk | last post by:
Hi, I get an overload resolution failed error (Overload resolution failed because no accessible 'New' can be called without a narrowing conversion), and I can't seem to find a lot of relevant...
5
by: Gang Zhang | last post by:
Hi, I have 2 overloaded functions as below: myfunc(byval val as Decimal) as string myfunc(byval val as String) as string When calling the function with a single like: dim num1 as single...
2
by: jason | last post by:
Since going to framework 2.0 from 1.1, I'm getting error: Overload resolution failed because no accessible 'New' can be called without a narrowing conversion: On line: Dim LogInfo As New...
2
by: sri | last post by:
class Base { public: virtual void f(int) { std::cout<<"base.f(int)\n";}; virtual void f(std::complex<double>) { std::cout<<"derived.f \n"; }; }; class Derived : public Base {
1
by: =?Utf-8?B?QU1lcmNlcg==?= | last post by:
I have a strange situation with vb 2005 regarding option strict that looks like a compiler bug to me. Consider: Dim f1 As New Font("Arial", 8.25) Dim f2 As New Font("Arial", 8.25,...
9
by: Anthony Williams | last post by:
Hi, Should the following compile, and what should it print? #include <memory> #include <iostream> void foo(std::auto_ptr<intx) { std::cout<<"copy"<<std::endl;
9
by: sebastian | last post by:
I've simplified the situation quite a bit, but essentially I have something like this: struct foo { }; void bar( foo const & lhs, foo const & rhs )
5
by: jknupp | last post by:
In the following program, if the call to bar does not specify the type as <int>, gcc gives the error "no matching function for call to ‘bar(A&, <unresolved overloaded function type>)’". Since bar...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.