Consider the example below:
class Base {
protected:
struct SubStruct { double value; };
};
class Derived : public Base {
public:
Derived() {
data.value = 3.14;
}
Base::SubStruct data;
};
int main()
{
Derived instance;
std::cout << instance.data.value << std::endl;
return 0;
}
The Derived class has the data member of the type that is defined in its base class. Pay special attention to that the SubStruct type is protected in Base.
Now I'm enhancing the Base with a choice of substructs. To select which substruct to use I'm making the Derived template:
class Base {
protected:
struct SubStructInt { int value; };
struct SubStructDouble { double value; };
};
template<typename S>
struct Derived : public Base {
Derived() {
data.value = 3.14;
}
S data;
};
int main()
{
Derived<Base::SubStructInt> instanceInt;
std::cout << instanceInt.data.value << std::endl;
Derived<Base::SubStructDouble> instanceDouble;
std::cout << instanceDouble.data.value << std::endl;
return 0;
}
That doesn't compile because the substructs are protected, and I cannot instantiate the Derived with the types protected in Base (everything works if I make them public).
I don't want to make the substructs public, so I found a solution with std::conditional:
template<bool flag>
struct Derived : public Base {
using SubStruct = std::conditional_t<flag, SubStructInt, SubStructDouble>;
Derived() {
data.value = 3.14;
}
SubStruct data;
};
Anyway, I think that this is not the best/idiomatic solution to the problem: "how to say to the derived class which protected type of the base class to use". At the end of the day the protected subtypes are visible within Derived, and can be aliased from there:
template<typename S>
struct Derived : public Base {
using DerivedInt = Derived<SubStructInt>;
using DerivedDouble = Derived<SubStructDouble>;
// ...
};
Is there a better way?