The best alternative solution for making constant inheritance (or read-only inheritance or you call whatever you want) in C++ that I came up with so far

03/23/2014

In this page, I am posting the best solution toward constant inheritance in C++ that I came up with so far.  I believe many people are trying but failing to make a const inheritance in C++.  I think some call it read-only inheritance.  You can call it whatever you want.  I'm calling it const inheritance.  I spent good amount of time searching for a solution, but I couldn't find a good solution.

What I want to do is this:

class YsShell
{
public:
    // Something useful
};

class YsShellExt : private YsShell
{
public:
    operator const YsShell &() const;
};

YsShellExt is privately derived from YsShell.  So, I want to mostly prohibit access to YsShell through YsShellExt.  But, I want to open constant access to YsShell by the conversion operator.

However, C++ specification apparently doesn't allow you to do it.  If you write like:

void SomeFunction(const YsShell &shl);

YsShellExt shlExt;
SomeFunction(shlExt);

The compiler will give you an error.  It won't look at the conversion operator that is explicitly declared as public.  The C++ rule apparently does not allow automatic conversion to the base class if the inheritance is private or protected.

Unless you come up with a trick, the only way to pass a const YsShell reference to the function is through static cast:

 YsShellExt shlExt;
SomeFunction((const YsShell &)shlExt);  // Possible, but want to avoid static cast.

But, I want to avoid static cast.  It will disable type check.  The point is I want to avoid typing (const YsShell &) here.  I want the C++ compiler automatically find a valid conversion and give it to the function.

I have tried to find a good solution myself several times in the past with no success.  But, I recently came up with the best closest solution through the converter class.  I can make converter classes in YsShellExt class like:

class YsShell
{
public:
    // Something useful
};

class YsShellExt : private YsShell
{
public:
    class Converter
    {
    public:
        YsShellExt *shl;
        operator const YsShell &() const
        {
            return *(const YsShell *)shl;
        }
        operator YsShellExt &() const
        {
            return *shl;
        }
    };
    class ConstConverter
    {
    public:
        const YsShellExt *shl;
        operator const YsShell &() const
        {
            return *(const YsShell *)shl;
        }
        operator const YsShellExt &() const
        {
            return *(const YsShellExt *)shl;
        }
    };

    inline Converter Conv(void)
    {
        Converter conv;
        conv.shl=this;
        return conv;
    }
    inline ConstConverter Conv(void) const
    {
        ConstConverter conv;
        conv.shl=this;
        return conv;
    }
};

When I want to pass to a function a YsShellExt object as a const YsShell &, I can write:

YsShellExt shlExt;
SomeFunction(shlExt.Conv()); // No static cast.  Compiler will catch if the receiving type is incompatible.

A Converter object can be automatically casted into const YsShell &, const YsShellExt &, or YsShellExt &.  If shlExt is const, a ConstConverter class will be used and can be automatically casted into const YsShell & or const YsShellExt &.  The compiler will pick the right conversion.  I avoid static cast here.  A Converter object is as big as a pointer, and the time for copying it is negligible.

If you want to go strict RIAA, you can also pass the this pointer to a Converter object through the constructor, but I like my way of writing because it simply keeps it POD.