Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

template parameter redeclaration

Tags:

c++

templates

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)

like image 339
Neel Basu Avatar asked Aug 05 '12 06:08

Neel Basu


People also ask

What is a template parameter?

Explanation: A template parameter is a special kind of parameter that can be used to pass a type as argument.

What is a non type template parameter?

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.

Which is the correct example of template parameters?

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.

How do you use template arguments in C++?

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.)


1 Answers

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;
};
like image 98
Johan Lundberg Avatar answered Oct 13 '22 04:10

Johan Lundberg