Reputation: 51
I am trying to compile the following snippets of code. Please check the errors I am getting at the end.
#include "Tree.h"
template <class T>
CNode<T>* CNode<T>::GetChild(const T& kData)
{
for( std::vector< CNode >::iterator it = m_vChildren.begin(); it!= m_vChildren.end(); ++it)
{
if(*it== kData)
{
return &(*it);
}
}
}
Tree.h (Header file):
#include "../include_m.h"
#include <vector>
template <class T>
class CNode
{
public:
CNode(const T& kData)
{
m_Data = kData;
}
void AddChildNode(const CNode& kcChildNode);
void DeleteChildNode(const T& kData);
void GetChildNode(const T& kData) const;
void Print();
private:
T m_Data;
std::vector<CNode> m_vChildren;
CNode * GetChild(const T& kData);
};
This fails to compile with the following errors:
g++ -o tree Tree.cpp
Tree.cpp: In member function ‘CNode<T>* CNode<T>::GetChild(const T&)’:
Tree.cpp:12: error: expected `;' before ‘it’
Tree.cpp:12: error: ‘it’ was not declared in this scope
Upvotes: 0
Views: 124
Reputation: 4708
All you're missing is a typename
before std::vector< CNode >::iterator
. Since CNode<T>::GetChild
is a templated context, the compiler can't know whether std::vector< CNode >::iterator
is a type or a value member. You could for instance have a template specialization of std::vector<CNode<int> >
where iterator
is defined as a class field. You need to use the typename
keyword to resolve this ambiguity.
On a relevant note, there's an even trickier situation where you need the template
keyword, and it might be worth mentioning here, consider:
template <class T>
struct C {
template <class U>
void memfunc();
};
template <class T>
void func() {
C<T> c;
c.template memfunc<int>();
}
You need the odd template
keyword in the last line there, since due to a similar reason to your problem, the compiler can't know that the member is in fact a template method in all specializations of the class C
. The error messages you get with this is also quite odd and they puzzle me every time.
The other answers also have a relevant point about having a template definition in a .cpp
file. You should probably follow their advice and move the definition to a .h
file. However, there actually are circumstances where you want a template definition in a .cpp
file. For instance, it might be that the method is only used in the same .cpp
file. Or you might want to take control of what types you want the templated member function to be instantiated with using explicit instantiation. You would achieve this with:
template class CNode<int>; // explicitly instantiate CNode<int>
template CNode<double>* CNode<double>::GetChild(const double& kData); // explicitly instantiate only the GetChild method for CNode<double>
This way, you won't have to recompile every .cpp
file that includes tree.h
whenever you make a change to the implementation of the GetChild
method.
Upvotes: 2
Reputation: 1004
.cpp
file with a template class. Everything must be in the .h
.CNode
in your header to indicate return types, values placed inside std::vector
s and parameters. These all have to be changed to CNode<T>
.This is because CNode
does not exist as a class in itself, but rather a template for classes to be created from at compile time. For every type placed inside <T>
; a new class is created at compile time.
Meaning CNode<X>
is not the same class as CNode<Y>
, and CNode
does not exist at all in the binary/executable.
This means that you can never reference CNode, or its members, without providing a value for <T>
.
Upvotes: 0