This is what I want to achieve. The leaf component will inherit Component<ParentT>, others will inherit Component<ParentT, ChildT>
template <typename T>
class Component{
protected:
typedef Component<T> ParentComponentT;
...
};
template <typename ParentT, typename ChildT>
class Component: public Component<ParentT>{
protected:
typedef std::vector<ChildT*> CollectionT;
...
};
But the problem is Template parameters getting redeclared. and I cannot move the second one above first one because second one inherits first one.
error: redeclared with 2 template parameter(s)
note: previous declaration ‘template class Component’ used 1 template parameter(s)
Explanation: A template parameter is a special kind of parameter that can be used to pass a type as argument.
A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument. A non-type parameter can be any of the following types: An integral type. An enumeration type. A pointer or reference to a class object.
For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.
A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
This compiles and as far as I understand does what you like:
#include <vector>
class NoneT {};
template <typename ParentT,typename ChildT=NoneT>
class Component: public Component<ParentT>{
protected:
typedef std::vector<ChildT*> CollectionT;
};
Specialization for NoneT:
template<>
template<typename T>
class Component<T,NoneT>{
protected:
typedef Component<T> ParentComponentT;
};
int main(){
typedef Component<double> someT;
typedef Component<double,int> someT2;
typedef Component<double,void> someT3;
}
someT will have ParentComponentT and someT2 will have CollectionT.
EDIT:
Answer to comment/question below: typename ChildT=noneT means that the default ChildT will be noneT. So, if no second template argument is given the noneT type will be used.
The specialization then defines the class content for the that one-argument version.
EDIT2:
Since I know from the chat that you use Component as a base class, I suggest that instead of something like
class myclass: public Component<Section, Line>
you could use multiple inheritance
class myclass: public ParentComponent<Section>, CollectionComponent<Line>
with
template <typename T>
class ParentComponent{
protected:
typedef Component<T> ParentComponentT;
};
template <typename ChildT>
class CollectionComponent {
protected:
typedef std::vector<ChildT*> CollectionT;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With