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