Dealing with an opaque objects hierarchy
| 
   "even monoliths can have a family" 2012 by Arnaud Sintès   Keywords: architecture, c++, interface, multiple-inheritance, template
  specialization   As an introduction note, please refer to my previous document
  about the opaque objects and the specialized template interfaces concept.  | 
 
  

We’ve seen before the interest to add multiple interfaces access to your object to keep the full control over the user’s visibility of its content.
It was called full
opaque objects (http://www.silentbreed.com/opaque/).
This is great, but you may be afraid to generalize this approach
of object implementation by considering a classic object hierarchy with a lot
of parent/child dependencies which
will have to deal with crossed access over
all these objects interfaces.
Let’s consider a simple class hierarchy were two objects (‘A’ and ‘B’) have to be accessed in read only mode at some point and in read/write mode somewhere else.

Writing the ‘B’ class with its interfaces is easy:
| 
   // ---------- // interface access
  types class Read; class ReadWrite;         // ---------- // 'B' templatized
  interfaces declaration template< class
  T = void > class
  IB {}; // Read interface
  access to 'B' template<> __interface IB< Read > {        const void
  GetSomething() const; }; // Read/Write
  interface access to 'B' template<> __interface IB< ReadWrite > {        const void
  GetSomething() const;        void SetSomething(); }; // ---------- // 'B' object
  definition class B sealed        :
  public IB< Read >        ,
  public IB< ReadWrite > { private: //
  IB< Read, ReadWrite >        const void
  GetSomething() const sealed
  {}        void SetSomething() sealed
  {} };  | 
 
The problem we have to consider is how to get the read only access interface of ‘B’ through the read only access interface of ‘A’, and how to get the read/write access interface of ‘B’ through the read/write access interface of ‘A’.
To be more clear, we hope to get a single method “GetB()” in both read only and read/write interfaces of ‘A’ to get a const IB< Read > interface in the first case and a IB< ReadWrite > interface in the second one.
| 
   // ---------- // interface access
  types class Read; class ReadWrite;         // ---------- // 'A' templatized
  interfaces declaration template< class
  T = void > class
  IA {}; // Read interface
  access to 'A' template<> __interface IA< Read > {        // through the IA< Read > interface, we want GetB()
  to return a const IB< Read > interface        const IB< Read > & GetB() const; }; // Read/Write
  interface access to 'A' template<> __interface IA< ReadWrite > {        // through the IA< ReadWrite > interface, we want
  GetB() to return a IB< ReadWrite > interface        IB<
  ReadWrite > & GetB() const;        void SetSomething(); };  | 
 
The answer is... it’s fucking trivial, thank you C++! J
You will just have to define a single sealed “GetB()” method in your inherited class which will return the base ‘B’ class reference, then the compiler smartly collapse both definitions into the implementation thanks to the inheritance magic.
| 
   // ---------- // 'A' object
  definition class A sealed        :
  public IA< Read >        ,
  public IA< ReadWrite > { private:        // the two interfaces definition will collapse to the
  same implementation        B
  & GetB() const sealed
  { return m_b; }        void SetSomething() sealed
  {} private:        mutable B m_b; };  | 
 
Let’s demo this:
| 
   void Demo() {        // get a Read interface of a new 'A' object        IA<
  Read > & A_R = *new A();        // GetB() will return the const Read version of 'B'        const IB< Read > & B_R = A_R.GetB();        B_R.GetSomething();        // get the Read/Write interface of a new 'A' object        IA<
  ReadWrite > & A_RW = *new A();        // GetB() will return the Read/Write version of 'B'        IB<
  ReadWrite > & B_RW = A_RW.GetB();        B_RW.GetSomething();        B_RW.SetSomething(); }  | 
 
That’s all folks, hope this help!
