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              ]