This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [93J20] C++ private inheritance in several steps



Mr. Eriksson,

    It seems that the simple class hierarchy in your example is
falling prey to a strict interpretation of a late change made just
before the C++ standard was approved.  The feature is known as
class name injection, and we describe it and its annoying 
consequences at
http://www.kai.com/C_plus_plus/v3.4/doc/UserGuide/chapter_9.html#class-name-injection

This together with the member access rules of section 11
(one of which notes that:
11.2.3: [Note: A member of a private base class might be inaccessible as an inherited member name, but
accessible directly. Because of the rules on pointer conversions (conv.ptr) and explicit casts
(expr.cast), a conversion from a pointer to a derived class to a pointer to an inaccessible base class
might be ill-formed if an implicit conversion is used, but well-formed if an explicit cast is used.
...]

... and with the rules of derived class name lookup

have combined to produce this code's inability for class C to
refer to the public class A directly.  When I compile using
--no_class_name_injection your original code works
as it always did. I tried to follow the standards advice of using
fully qualified names more often, and I just got into more
trouble.  What turned out to work was Arch Robison's suggestion
from our website, that you insert a typedef to explicit export
from B the typename of A.  

Frankly it looks a little ridiculous, but in the world of access
control, it probably makes sense.  Fortunately it is not my job to
defend the ISO committee's design.

Greg Jaxon
KAI Optimizing Compilers

class A {
  public: A(int d=17) : data(d) {}; int data;
};
class B : private A {
 public:
   typedef A A;                                    // <<<<< inserted
   const A& getA() const {return *this;}
};
class C : private B {
public: const A& getA() const {return B::getA();}
};

#include <iostream>

using namespace std;

int main()
{
  C c0;
  cout << "c0.getA().data: " << c0.getA().data << endl;
  return 0;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]