Topic: Pointers to member, virtual inheritance, and compilers...
Author: joerg.barfurth@attglobal.net (Joerg Barfurth)
Date: 2000/07/25 Raw View
<pescio@my-deja.com> wrote:
> Recently I've written some toy code to discover, at compile time, if a
> class inherits from another via non-virtual inheritance.
> I have found (as expected :-) that compilers treat it differently. Here
> is a version that happens to compile with MS VC++ 6, GNU 2.95, Borland
> 5.5, but not with Comeau 4.2.43 Beta #1.
> template< class T > struct S
> {
> S( int T::* ) ;
> } ;
>=20
> template< class T1, class T2 > struct Constraint
> {
> static char IsNVBase( int T2::* ) ;
> static long IsNVBase( S< T1 > ) ;
> } ;
>=20
> class Base
> {
> } ;
> class VirtualDerived : virtual public Base
> {
> } ;
> Moreover, Comeau C++ reports an error for the line
>=20
> int x2 =3D sizeof( Constraint< Base, VirtualDerived >::IsNVBase( (int
> Base::*) 0 ) ) ;
>=20
> The error message points out (correctly) that Base is a virtual base
> class of VirtualDerived, so a conversion is illegal. I suppose this
> means that IsNVBase( int T2::* ) is selected as viable.
> Still, as I read the standard (maybe I'm wrong, and I'll appreciate
> corrections) in this case the compiler shouldn't even try this illegal
> conversion (like any other illegal conversion :-) and should select the
> IsNVBase S< T1 > as the only viable function, just like it does for x1
> (where the ptr-to-member conversion would be illegal as well, for other
> reasons).
After looking at 4.11/2 and 13.3.3.1/2, I think that Como is right to
reject the code.
4.11/2 states that
-A pointer to base class member of type T can be converted to a pointer
to derived class member of type T. Period.
- If the base class is virtual or inaccessible or ambiguous "a program
that necessitates this conversion is ill-formed.
Summarized,this reads like: The conversion is there , but it may be
illegal. The case of a virtual base class is somehow on par with the
case of an inaccessible base- and it is checked for only when the
conversion has been selected.
13.3.3.1/2 states that implicit conversion sequences (used for overload
resolution) are concerned only with the type (etc...) of the argument.
It continues to say that other properties _such as accessibility_ are
ignored. So although a conversion is found ... it may still be
ill-formed in the final analysis.
This would mean that indeed:
- IsNVBase( int T2::* ) is considered viable
- That function is then selected (as best match)
- The call thus 'necessitates this conversion'=20
- and thereby is ill-formed :-(
> Opinions, suggestions, reports from other compilers would be much
> appreciated.
HTH
Ciao J=F6rg
--=20
J=F6rg Barfurth joerg.barfurth@attglobal.net
-------------- using std::disclaimer; -----------------------------
Download: StarOffice 5.2 at http://www.sun.com/staroffice
Participate: OpenOffice now at http://www.OpenOffice.org
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: pescio@my-deja.com
Date: 2000/07/21 Raw View
Recently I've written some toy code to discover, at compile time, if a
class inherits from another via non-virtual inheritance.
I have found (as expected :-) that compilers treat it differently. Here
is a version that happens to compile with MS VC++ 6, GNU 2.95, Borland
5.5, but not with Comeau 4.2.43 Beta #1.
More elegant versions didn't compile with GNU and Borland (Borland
reported an internal compiler error), and also with Comeau (with a
different error reported).
template< class T > struct S
{
S( int T::* ) ;
} ;
template< class T1, class T2 > struct Constraint
{
static char IsNVBase( int T2::* ) ;
static long IsNVBase( S< T1 > ) ;
} ;
class Base
{
} ;
class Other
{
} ;
class Derived : public Base
{
} ;
class VirtualDerived : virtual public Base
{
} ;
#include <iostream>
int main()
{
// the usual technique of moving the right side into an enum
// inside Constraint makes some compilers unhappy.
int x3 = sizeof( Constraint< Base, Derived >::IsNVBase( (int Base::*)
0 ) ) ;
int x2 = sizeof( Constraint< Base, VirtualDerived >::IsNVBase( (int
Base::*) 0 ) ) ;
int x1 = sizeof( Constraint< Base, Other >::IsNVBase( (int Base::*)
0 ) ) ;
std::cout << x1 <<" " << x2 << " " << x3 << "\n" ;
return( 0 ) ;
}
I would expect the code to print something along the lines of 4 4 1
(change 4 to whatever sizeof(long) is on the specific platform).
Still:
VC++ 6, GNU 2.95, Borland 5.5 print 4 1 1. They don't seem to respect
the standard (4.11p2, a pointer to base-class member can be converted
to a pointer to derived-class member only if the base class is
accessible, unambiguous, and _nonvirtual_).
Moreover, Comeau C++ reports an error for the line
int x2 = sizeof( Constraint< Base, VirtualDerived >::IsNVBase( (int
Base::*) 0 ) ) ;
The error message points out (correctly) that Base is a virtual base
class of VirtualDerived, so a conversion is illegal. I suppose this
means that IsNVBase( int T2::* ) is selected as viable.
Still, as I read the standard (maybe I'm wrong, and I'll appreciate
corrections) in this case the compiler shouldn't even try this illegal
conversion (like any other illegal conversion :-) and should select the
IsNVBase S< T1 > as the only viable function, just like it does for x1
(where the ptr-to-member conversion would be illegal as well, for other
reasons).
Opinions, suggestions, reports from other compilers would be much
appreciated.
Have fun,
Carlo Pescio
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]