I have a quite niche problem concerning private inheritance. I also have a solution for the problem, but I don't understand why it works.
TL;DR
Why does private inheritance on some intermediate level prevent me from passing the base type as a parameter to a (privately) derived class?
Consider the following code (also available here http://cpp.sh/3p5zv5): I have a composite-type class that can contain pointers to child elements of its own type. Also, that class contains the template method MyMethodTemplate(T value), allowing any type of Parameter. I need to inherit from this class multiple times, such that MyMethodTemplate(T) is not available, and instead only a typed version MyMethod() can be called with e.g. int, string, whatever.
Since the derived classes were going to contain a lot of boilerplate code (not shown here), I wrote the class template cSpecializedComposite that inherits privately from cComposite (successfully hiding MyMethodTemplate()). Its method MyMethod() internally calls MyMethodTemplate() from its parent class. So far, so good.
Now, to get rid of the template parameter in my end user code, I wanted to write trivial classes that publicly inherit from the template (cSpecializedCompositeInt, cSpecializedCompositeString, ...). My assumption was that cSpecializedCompositeInt would know cSpecializedComposite's interface, but not its internals. In cSpecializedCompositeInt's constructor, I can optionally pass a vector of unique_ptr that is passed on to its parent constructor (who does god knows what with it, nothing to see here, move along). Note that the class definition for cComposite is visible to cSpecializedCompositeInt, even if cSpecializedCompositeInt doesn't inherit from it, as far as it knows.
However, I get a compiler error C2247 in cSpecializedCompositeInt's constructor, telling me I can't use cComposite, because cSpecializedComposite inherited privately from it. This occured on both msvc10 and GCC 4.9.2 (the compiler behind http://cpp.sh).
Changing the private inheritance to protected allows cSpecializedCompositeInt to know it inherited indirectly from cComposite, and the compiler error goes away.
In how far is this related to Private Inheritance and Derived Object to Base reference ?
#include <vector>
#include <memory>
class cComposite
{
public:
cComposite(std::vector<std::unique_ptr<cComposite>>&& vecC)
: m_vecC(std::move(vecC))
{
//empty
}
template <typename T>
void MyTemplateMethod(T value)
{
//do something with any type of value
}
private:
std::vector<std::unique_ptr<cComposite>> m_vecC;
};
template <typename MySpecialType>
class cSpecializedComposite : private cComposite
{
public:
cSpecializedComposite(std::vector<std::unique_ptr<cComposite>>&& vecC)
: cComposite(std::move(vecC))
{
//empty
}
void MyMethod(MySpecialType value)
{
//allow only MySpecialType as Input, call base class template method to do something
cComposite::MyTemplateMethod(value);
}
};
class cSpecializedCompositeInt : public cSpecializedComposite<int>
{
public:
cSpecializedCompositeInt(std::vector<std::unique_ptr<cComposite>>&& vecC)
: cSpecializedComposite(std::move(vecC))
{
//empty
}
};
int main(int argc, char* argv[])
{
std::vector<std::unique_ptr<cComposite>> vecC;
cSpecializedCompositeInt spec(std::move(vecC));
spec.MyMethod(5);
return 0;
}