mercredi 23 décembre 2015

Private base class affects member access via template friend function and template method in child class

First of all, sorry for the length title. I encountered a weird issue where, the existence of a private base of the same type as a member shaddows access to the member in a child class but not outside the child class definition. Look at the following code:

 struct PrivateBase {};

 struct Base : private PrivateBase {
   // Member accessors.
   PrivateBase* GetPrivateBase() { return &a; }

   template<typename T>
   T* GetPrivateBase() { return &a; }

   // Free function accessors.
   friend PrivateBase* FreeGetPrivateBase(Base* b) { return &(b->a); }

   template<typename T>
   friend T* FreeGetPrivateBase(Base* b);

  private:
   // This member has nothing to do with the PrivateBase base class.
   PrivateBase a;
 };

 template<typename T>
 T* FreeGetPrivateBase(Base* b) { return &(b->a); }

 struct Child : public Base {
   void SomeFunc() {
     // Works!1!!.
     GetPrivateBase();

     // Doesn't work.
     //GetPrivateBase<PrivateBase>(); // (1)

     // Works!1!!.
     FreeGetPrivateBase(this);

     // Doesn't work.
     //FreeGetPrivateBase<PrivateBase>(this);
   }
 };

 int main() {
   Child c;

   // Works!1!!.
   c.GetPrivateBase<PrivateBase>();

   // Works!1!!.
   FreeGetPrivateBase<PrivateBase>(&c);

   return 0;
 }

I've tried to compile this both, with g++-4.8.4 and clang++-3.7.1. With clang and (1) uncommented I get:

minimal.cc:30:20: error: 'PrivateBase' is a private member of 'PrivateBase'
    GetPrivateBase<PrivateBase>();
                   ^
minimal.cc:3:15: note: constrained by private inheritance here
struct Base : private PrivateBase {
              ^~~~~~~~~~~~~~~~~~~
minimal.cc:1:8: note: member is declared here
struct PrivateBase {};
       ^

The fun fact is that access to a works outside of Child and inside Child with the non-templated accessors. It also works inside Child with the templated accessors if I get rid of the private base class. I would love to blame it on the compiler but unconventionally enough both contenders seem to agree. Could anybody explain the interplay between templated accessors, child scope and private base class? - Thanks.

Aucun commentaire:

Enregistrer un commentaire