C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Derived to Base conversions - what does the standard say?

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Puverle, Tomas (IT)
Guest





PostPosted: Wed Oct 27, 2004 1:03 am    Post subject: Derived to Base conversions - what does the standard say? Reply with quote



Consider the following:

class X {};
class Y:public X {};
class Z:public Y {};

void f(const X&); //1
void f(const Y&); //2

int main()
{
Z z;
f(z);
}

Which one of the f()s should be called? (Btw g++ says it should be 2).
Where is the rationale in the standard?

The reason why I ask is I ran into some problems with code similar to
this:

template<class T>
class X
{};

template<>
class X<int>:public X<double>
{};

class G: public X<int>
{};

template<class T>
void f(X<T>&)
{}

int main()
{
G g;
f(g);
}

Which is basically the same as the example above, but both g++ and
Comeau fail to compile this saying "no matching function for call to
`f(G&)'"

What's right (with references please), what's not and what are just
compiler bugs?

Thanks!

Tom
--------------------------------------------------------

NOTICE: If received in error, please destroy and notify sender. Sender does
not waive confidentiality or privilege, and use is prohibited.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
rishi
Guest





PostPosted: Wed Oct 27, 2004 2:05 pm    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote



"Puverle, Tomas (IT)" <Tomas.Puverle (AT) morganstanley (DOT) com> wrote

Quote:
Consider the following:

class X {};
class Y:public X {};
class Z:public Y {};

void f(const X&); //1
void f(const Y&); //2

int main()
{
Z z;
f(z);
}

Which one of the f()s should be called? (Btw g++ says it should be 2).


"Puverle, Tomas (IT)" <Tomas.Puverle (AT) morganstanley (DOT) com> wrote


Quote:
Consider the following:

class X {};
class Y:public X {};
class Z:public Y {};

void f(const X&); //1
void f(const Y&); //2

int main()
{
Z z;
f(z);
}

Which one of the f()s should be called? (Btw g++ says it should be 2).
Where is the rationale in the standard?

The function overload resolution mechanism deems 2 to be called in

priority to
1. This is because in the standard somewhere it says that if
Y is derived from X directly/indirectly and Z is derived
directly/indirectly
from Y then implicit conversion of Z* to Y* is a betten conversion
than Z* to X*.

I do not have the standard handy at them moment but you should check
the
function overload matching implicit conversion best match as keywords
in the std.


Quote:
Where is the rationale in the standard?

rationale:
1) one approach could be to disallow implicit conversions. This works
against the grain of c++ programmers.
2) if there is an implicit conversion allowed then
func(X const&) and
func(Y const&) are both candidates.
The func(Y const&) is a better match as it is closer to the interface
of Z than
X.
struct X{
func1();
};
struct Y:X{
func2();
};
struct Z:Y{
func3();
};
Z at this stage contains func1,func2,func3 names . Y contains
func1,func2 names
and X just contains func1.
plus Y must have hidden away some names of X by redefining the same
names.

All this makes Y a closer interface to Z than is X.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Victor Bazarov
Guest





PostPosted: Wed Oct 27, 2004 2:25 pm    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote



"Puverle, Tomas (IT)" <Tomas.Puverle (AT) morganstanley (DOT) com> wrote...
Quote:
Consider the following:

class X {};
class Y:public X {};
class Z:public Y {};

void f(const X&); //1
void f(const Y&); //2

int main()
{
Z z;
f(z);
}

Which one of the f()s should be called? (Btw g++ says it should be 2).
Where is the rationale in the standard?

13.3.3.2/4 A conversion to a direct base is ranked better than a conversion
to an indirect base.

Quote:
The reason why I ask is I ran into some problems with code similar to
this:

template<class T
class X
{};

template
class X {};

class G: public X {};

template void f(X {}

int main()
{
G g;
f(g);
}

Which is basically the same as the example above, but both g++ and
Comeau fail to compile this saying "no matching function for call to
`f(G&)'"

It's definitely not the same. A completely different clause of the
Standard is involved. Templates. Complicated...

Quote:
What's right (with references please), what's not and what are just
compiler bugs?

The compiler is trying to determine what 'T' should be. I tried to
understand why it can't do that, but, to be honest, failed. The same
code compiles fine with Visual C++ v7.1.

V


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Michiel Salters
Guest





PostPosted: Thu Oct 28, 2004 1:55 pm    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote

"Puverle, Tomas (IT)" <Tomas.Puverle (AT) morganstanley (DOT) com> wrote

Quote:
Consider the following:

class X {};
class Y:public X {};
class Z:public Y {};

void f(const X&); //1
void f(const Y&); //2

int main()
{
Z z;
f(z);
}

Which one of the f()s should be called? (Btw g++ says it should be 2).
Where is the rationale in the standard?

f(Y const&), it's a better match. The second conversion Z->Y is a
subsequence of the first Z->Y->X

Quote:
The reason why I ask is I ran into some problems with code similar to
this:

template<class T
class X
{};

template
class X {};

class G: public X {};

template void f(X {}

int main()
{
G g;
f(g);
}

Which is basically the same as the example above, but both g++ and
Comeau fail to compile this saying "no matching function for call to
`f(G&)'"

The difference is that f used to be an non-template
overload set, but here it is a single function template.
In addition, the instantiated verions would differ because
you dropped the const as well.

To get to overload resolution, the compiler would first need to
instantiate f. There is no T such that X<T> equals G. Therefore
g++ and Comeau are right.

Regards,
Michiel Salters

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Tom
Guest





PostPosted: Fri Oct 29, 2004 1:44 am    Post subject: A bug in Comeau and g++? [Was: Derived to Base conversions] Reply with quote

Quote:
The compiler is trying to determine what 'T' should be. I tried to
understand why it can't do that, but, to be honest, failed. The same
code compiles fine with Visual C++ v7.1.

Like you describe, I just can't see why this doesn't work. Hence my
questioning of my understanding of what's going on... I am glad to see I am
not going completely crazy.
Is this a bug in the compilers then? (Btw I tried this with Comeau online
and g++ 3.2.3-20)

Tom



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Vladimir Marko
Guest





PostPosted: Fri Oct 29, 2004 2:12 am    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote

"Puverle, Tomas (IT)" <Tomas.Puverle (AT) morganstanley (DOT) com> wrote

Quote:
Consider the following:

class X {};
class Y:public X {};
class Z:public Y {};

void f(const X&); //1
void f(const Y&); //2

int main()
{
Z z;
f(z);
}

Which one of the f()s should be called? (Btw g++ says it should be 2).
Where is the rationale in the standard?

The reason why I ask is I ran into some problems with code similar to
this:

template<class T
class X
{};

template
class X {};

class G: public X {};

template void f(X {}

int main()
{
G g;
f(g);
}

Which is basically the same as the example above, but both g++ and
Comeau fail to compile this saying "no matching function for call to
`f(G&)'"

What's right (with references please), what's not and what are just
compiler bugs?

<quote 14.8.2.1/3>
In general, the deduction process attempts to find template
argument values that will make the deduced A identical to A (after the
type A is transformed as described above). However, there are three
cases that allow a difference:

- [snip: more cv-qualified reference]
- [snip: qualification conversion]
- If P is a class, and P has the form template-id, then A can be
a derived class of the deduced A. Likewise, if P is a pointer to
a class of the form template-id, A can be a pointer to a derived
class pointed to by the deduced A.

These alternatives are considered only if type deduction would otherwise
fail. If they yield more than one possible deduced A, the type deduction
fails. [snip: note]
</quote>

Your first snippet is about overload resolution and Victor Bazarov
already wrote that 13.3.3.2/4 applies. In the second case the template
argument deduction comes first. The third bullet of 14.8.2.1/3 would
allow both int and double as T, thus the last quoted sentence clearly
rules out the whole function template f. The overload resolution does
not play any role since it gets just an empty candidate list.

Vladimir Marko

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Daveed Vandevoorde
Guest





PostPosted: Fri Oct 29, 2004 2:26 pm    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote

"Victor Bazarov" <v.Abazarov (AT) comAcast (DOT) net> wrote:
Quote:
"Puverle, Tomas (IT)" <Tomas.Puverle (AT) morganstanley (DOT) com> wrote...
[...]
The reason why I ask is I ran into some problems with code similar to
this:

template<class T
class X
{};

template
class X {};

class G: public X {};

template void f(X {}

int main()
{
G g;
f(g);
}

Which is basically the same as the example above, but both g++ and
Comeau fail to compile this saying "no matching function for call to
`f(G&)'"

It's definitely not the same. A completely different clause of the
Standard is involved. Templates. Complicated...

What's right (with references please), what's not and what are just
compiler bugs?

The compiler is trying to determine what 'T' should be. I tried to
understand why it can't do that, but, to be honest, failed. The same
code compiles fine with Visual C++ v7.1.

That's a Visual C++ bug. The relevant paragraphs in the standard are
14.8.2.1/1-5. In particular, paragraph 5 says that if there is more than
one possible deduced "A", the type deduction fails. Here the "A" mentioned
in the standard can be deduced as both X<int> and X<double>. Hence
the error.

Hope that helps,

Daveed

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Fri Oct 29, 2004 2:35 pm    Post subject: Re: A bug in Comeau and g++? [Was: Derived to Base conversio Reply with quote

Tom <NoSpam (AT) ThankYouVeryMuch (DOT) com> wrote


Quote:
The compiler is trying to determine what 'T' should be. I tried to
understand why it can't do that, but, to be honest, failed. The
same code compiles fine with Visual C++ v7.1.

Like you describe, I just can't see why this doesn't work. Hence my
questioning of my understanding of what's going on... I am glad to
see I am not going completely crazy.

Is this a bug in the compilers then? (Btw I tried this with Comeau online
and g++ 3.2.3-20)

I wonder if this doesn't fall under §14.8.2.4/4: a nondeduced context.
Off hand, it looks like it would.

I didn't answer earlier, because I'll admit that I have a lot of
difficulty understanding this section; I thought I'd wait until some
real expert spoke up. And the fact that some compilers accept it, and
others not, could be simply that some compiler authors are interpreting
this section differently than others.

--
James Kanze GABI Software http://www.gabi-soft.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Tom
Guest





PostPosted: Sun Oct 31, 2004 10:52 am    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote

Quote:
Which is basically the same as the example above, but both g++ and
Comeau fail to compile this saying "no matching function for call to
`f(G&)'"

It's definitely not the same. A completely different clause of the
Standard is involved. Templates. Complicated...

What's right (with references please), what's not and what are just
compiler bugs?

The compiler is trying to determine what 'T' should be. I tried to
understand why it can't do that, but, to be honest, failed. The same
code compiles fine with Visual C++ v7.1.

That's a Visual C++ bug. The relevant paragraphs in the standard are
14.8.2.1/1-5. In particular, paragraph 5 says that if there is more than
one possible deduced "A", the type deduction fails. Here the "A"
mentioned
in the standard can be deduced as both X<int> and X<double>. Hence
the error.

Thanks Daveed, and everyone else who also replied, very much appreciated.
It would be nice if this worked though... It strikes me as a bit of a
special case because there is the constraint of the inheritance
relationship.
Would you agree?

Tom






[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Victor Bazarov
Guest





PostPosted: Sun Oct 31, 2004 11:02 am    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote

Daveed Vandevoorde wrote:
Quote:
"Victor Bazarov" <v.Abazarov (AT) comAcast (DOT) net> wrote:

"Puverle, Tomas (IT)" <Tomas.Puverle (AT) morganstanley (DOT) com> wrote...

[...]

The reason why I ask is I ran into some problems with code similar to
this:

template<class T
class X
{};

template
class X {};

class G: public X {};

template void f(X {}

int main()
{
G g;
f(g);
}

Which is basically the same as the example above, but both g++ and
Comeau fail to compile this saying "no matching function for call to
`f(G&)'"

It's definitely not the same. A completely different clause of the
Standard is involved. Templates. Complicated...

What's right (with references please), what's not and what are just
compiler bugs?

The compiler is trying to determine what 'T' should be. I tried to
understand why it can't do that, but, to be honest, failed. The same
code compiles fine with Visual C++ v7.1.


That's a Visual C++ bug. The relevant paragraphs in the standard are
14.8.2.1/1-5. In particular, paragraph 5 says that if there is more than
one possible deduced "A", the type deduction fails. Here the "A" mentioned
in the standard can be deduced as both X<int> and X<double>. Hence
the error.

Thank you Daveed, this is very helpful. However, I still have a question
then. Is it due to overwhelming complexity that the deduction does not
involve the rules similar to overload resolution? Specifically, would it
be too difficult to see which conversion (since conversion is required) is
better, and since G&->X<int>& is better than G&->X<double>&, pick X<int>
and deduce that T==int?

I know, I know, it probably is going to be too much for compiler writers
to be feasible. I just thought that the mechanism for determining which
overloaded function to pick is already in the compiler, why not use it?

V

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Daveed Vandevoorde
Guest





PostPosted: Mon Nov 01, 2004 10:17 pm    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote

Victor Bazarov <v.Abazarov (AT) comAcast (DOT) net> wrote:
Quote:
Daveed Vandevoorde wrote:
"Victor Bazarov" <v.Abazarov (AT) comAcast (DOT) net> wrote:

"Puverle, Tomas (IT)" <Tomas.Puverle (AT) morganstanley (DOT) com> wrote...

[...]

The reason why I ask is I ran into some problems with code similar to
this:

template<class T
class X
{};

template
class X {};

class G: public X {};

template void f(X {}

int main()
{
G g;
f(g);
}
[...]
Thank you Daveed, this is very helpful. However, I still have a question
then. Is it due to overwhelming complexity that the deduction does not
involve the rules similar to overload resolution? Specifically, would it
be too difficult to see which conversion (since conversion is required) is
better, and since G&->X<int>& is better than G&->X<double>&, pick X and deduce that T==int?

I know, I know, it probably is going to be too much for compiler writers
to be feasible. I just thought that the mechanism for determining which
overloaded function to pick is already in the compiler, why not use it?

I don't think it was out of concern for implementation complexity, though
I'm not positive (I think the decision predates my attending the Core III
meetings, which were the ones dealing with this stuff).

My guess is that the concerns were more of a semantic nature: Are we very
sure that the more derived pick is the expected choice in typical use cases?
Also, I suspect there might have been a concern for specification cleanliness
(i.e., mixing overload resolution rules into deduction rules might create
quite a bit of additional mess).

Daveed

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Tom
Guest





PostPosted: Tue Nov 02, 2004 1:19 pm    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote

Quote:
My guess is that the concerns were more of a semantic nature: Are we very
sure that the more derived pick is the expected choice in typical use
cases?

I was really hoping someone would come back with this sort of answer: As in
"you can't do this because it will break xyz in the current spec".
Since noone discovered/had the same problems with this before presumably
it's not a very common usage pattern(?). I would argue, however, that the
semantics should be as close as possible to the non-template behaviour.
To be honest, despite the fact that I was actually aware of the C++ standard
sections you and others quoted, I still found the behaviour surprising (and
reading this group, I wasn't the only one), because intuitively it felt it
should work. Now I should have learn by now with C++ that doesn't often
really mean anything, but it was enough to give me doubts about whether I
was misreading/misunderstanding some parts of the standard.

Quote:
Also, I suspect there might have been a concern for specification
cleanliness
(i.e., mixing overload resolution rules into deduction rules might create
quite a bit of additional mess).

I see what you are getting at.
This behaviour must already be implemented in the overload rules, but the
question is whether this should be really be a part of the overloading part
of the standard, rather than template argument deduction?
I would argue that the template deduction process must select the most
specialised template type anyway (and here by type I will refer to the full
template typename, e.g. vector<int>). On the same grounds, the deduction in
our case should select the most specialised type again, but at this point
the "most specialised" is given meaning not by partial/explicit
specialisation but by inheritance.

Tom

P.S. when I use "argue" in the text I mean it in the nicest way possible.
I know arguing about anything from the standard with you would be futile ;)









[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kanze@gabi-soft.fr
Guest





PostPosted: Tue Nov 02, 2004 8:58 pm    Post subject: Re: Derived to Base conversions - what does the standard say Reply with quote

Tom <NoSpam (AT) ThankYouVeryMuch (DOT) com> wrote

Quote:
Which is basically the same as the example above, but both g++
and Comeau fail to compile this saying "no matching function for
call to `f(G&)'"

It's definitely not the same. A completely different clause of the
Standard is involved. Templates. Complicated...

What's right (with references please), what's not and what are
just compiler bugs?

The compiler is trying to determine what 'T' should be. I tried to
understand why it can't do that, but, to be honest, failed. The
same code compiles fine with Visual C++ v7.1.

That's a Visual C++ bug. The relevant paragraphs in the standard
are 14.8.2.1/1-5. In particular, paragraph 5 says that if there is
more than one possible deduced "A", the type deduction fails. Here
the "A" mentioned in the standard can be deduced as both X<int> and
X<double>. Hence the error.

Thanks Daveed, and everyone else who also replied, very much
appreciated. It would be nice if this worked though... It strikes me
as a bit of a special case because there is the constraint of the
inheritance relationship. Would you agree?

I think it is a case of separation of concerns. Templates aren't really
concerned with inheritance, for example. And the rules for template
instantiation and the rules for function overload resolution are
both complicated enough taken separately -- I certainly wouldn't like to
see additional interactions between them.

--
James Kanze GABI Software http://www.gabi-soft.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.