Question

My friend has shown me the follow code

struct A {
  virtual void f() = 0;
  virtual void g() = 0;
};

struct AInternal : A {
  virtual void f() { /* ... */ }
  virtual void g() { /* ... */ }
};

He is using AInternal as an internal class that implements most (if not all of A). He then inherited from AInternal, but as he wanted that AInternal stays inaccessible (since it is an implementation detail), he inherits protected (implemented in terms of). What he also did was usinging the base class name to make A accessible (it was protected by default, since AInternal was inherited protected too)

struct C : protected AInternal {
  using AInternal::A;
};

Actually, this worked fine (but as we later found, it still kept the member functions private - just the base class was made public), but it only worked on GCC. It fails to make base A accessible. Any idea? We could even make it to break code that works on Clang

struct C : public AInternal {
protected:
  using AInternal::A;
};

C *c = 0;
A *a = c; // error on GCC!

Can someone help out please?

Was it helpful?

Solution

You are only affecting the visibility of the injected-class-name. The access protection of the base subobject or its members should not be affected. If Clang or GCC allows it to affect a cast validity or access within the base, that's their bug.

[class.member.lookup] 10.2/3 says

In the declaration set, using-declarations are replaced by the members they designate, and type declarations (including injected-class-names) are replaced by the types they designate.

The base class subobject does not have a name in member lookup; the injected-class-name does.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top