I have a template and many derived classes. In all of these classes I want to use the template type and some dependent types of it (actually I have many types and many dependent types).
The following approach is quite bad, since I need to manually inherit (with using keyword) all the types from the parent class (see code example):
EDIT: I didn't know that it is important that the class where I want to use the types is also a template. I updated the code example accordingly.
template<class T>
class A {
using TBase = T;
using TDerived = T[10];
}
template<class T>
class B : A<T> {
// NOTE i want the types TBase and TDerived here and in further children
using TBase = A<T>::TBase;
using TDerived = A<T>::TDerived
}
class C : B<int> {
// NOTE i want the types TBase and TDerived here and in further children
using TBase = B<int>::TBase;
using TDerived = B<int>::TDerived
}
I also thought about templated namespaces so that I could define the types outside of the class - but they don't exist.
Does anyone have a better idea?
SOLUTION1: fix current approach
(based on the comments from Jan Hudec and the answer from Oguk)
- public inheritance
I forget the keywordpublic:
for classes (struct is public by default). - missing
typename
The compiler warning for my (wrong) types where used in the class where misleading (although the ones for theusing
keyword directly hint to the missingtypename keyword
).
Further notes about when to usetypename
can be found here: https://stackoverflow.com/a/7923419/3779655 - type interitance
When I correctly specify the type (e.g. see 2. missingtypename
) then I can also use the current class name.
Resulting code:
template<class T>
class A {
public:
using TBase = T;
using TDerived = T[10];
};
template<class T>
class B : public A<T> {
public:
// possiblity 1:
using TBase = typename B::TBase;
TBase memberB1;
// possibility 2
typename B::TBase memberB2;
};
class C : public B<int> {
public:
// NOTE C is no template -> we don't have to do anything
TBase memberC;
};
SOLUTION2: trait classes
(based on the answer from Oguk)
- use templated trait class instead of namespace
This gives pretty much the same functionality. - different availability of type information
One thing I didn't think of before is to check which type information is available where and if further characters are needed to retrieve the needed type information from a parent class (see NOTE comments).
See code below:
template<class T>
struct TypesContainer {
using TBase = T;
using TDerived = T[10];
};
template<class T>
class A {
public:
// TODO possible to directly inherit all types?
//using TypesContainer<T>;
// NOTE this is only possible for methods, not types
using Types = TypesContainer<T>;
typename Types::TBase memberA;
};
class B : public A<int> {
public:
// NOTE here I have all template information via definition (by hand)
using Types = TypesContainer<int>;
typename Types::TBase memberB;
};
class C : public B {
public:
// NOTE here I don't have the type information any more
using Types = TypesContainer<A::Types::TBase>;
typename Types::TBase memberC;
};
PROBLEM:
Is there a way to directly inherit all members of a namespace/class within the class scope (see TODO comment). Using the using
keyword without assignement operator =
does only work for methods not namespaces, classes and types.