Problems With Templates

T

Tayfun Özdemir

Hello there,

I have a school project and I have to finish it soon.

I have to implement B+ Tree for the project.

I have TreeNode template class. That will be used to hold keys in the tree
index.
I have LeafNode template class derivered from TreeNode. That will be used to
hold keys and values in leaf.

Everything seems fine but it does not compile under MS.Net and gcc. It
compiles Dev-C++ but linker can not find Insert function and gives error.

I have checked many resources but I could not find the error. I would be
glad if you could explain me what is wrong.

Errors I get
TreeNode.h(5): error C2059: syntax error : '<' (The same line with
template)
TreeNode.h(5): error C2143: syntax error : missing '{' before '<' (The same
line with template)
TreeNode.c(3): error C2059: syntax error : '<'

main.c(9): error C2059: syntax error : 'type'

and the list goes like this.

I would be glad if you could explain me what is wrong.


////////////// TreeNode.h////////////////
////////////// TreeNode.h////////////////
////////////// TreeNode.h////////////////
#ifndef __TREE_NODE__

#define __TREE_NODE__



template <class KeyType, class ValType, int SIZE>

class TreeNode

{

public:

TreeNode() : nCount(0)

{};

virtual void Insert(KeyType Key, ValType Val, KeyType &ParentKey,

TreeNode<KeyType, ValType, SIZE> *&LeftChild,

TreeNode<KeyType, ValType, SIZE> *&RightChild);



protected:

int nCount;

KeyType e_Keys[SIZE];

TreeNode<KeyType, ValType, SIZE> *e_Childs[SIZE];

};

#endif


////////////// LeafNode.h////////////////
////////////// LeafNode.h////////////////
////////////// LeafNode.h////////////////

#include "TreeNode.h"

#ifndef __LEAF_NODE__

#define __LEAF_NODE__

template <class KeyType, class ValType, int SIZE>

class LeafNode : public TreeNode<KeyType, ValType, SIZE>

{

public:

LeafNode()

{

nCount = 0;

};



virtual void Insert(KeyType Key, ValType Val, KeyType &ParentKey,

TreeNode<KeyType, ValType, SIZE> *&LeftChild,

TreeNode<KeyType, ValType, SIZE> *&RightChild);





protected:

ValType e_Vals[SIZE];

};



#endif



////////// Main.c for testing //////////////////

////////// Main.c for testing //////////////////

////////// Main.c for testing //////////////////

int main(int argc, char *argv[])

{

int a, b, c, d;

LeafNode<int, int, 7> TestNode;

TreeNode<int, int, 7> *e, *f;



TestNode.Insert(10, 10, a, e, f);



return 0;

}





Tayfun Ozdemir
 
T

Tayfun Özdemir

I can send you all of my program if that helps.
Sincerely.
Tayfun Özdemir.
 
J

Jonathan Mcdougall

Tayfun said:
Hello there,

I have a school project and I have to finish it soon.

I have to implement B+ Tree for the project.

I have TreeNode template class. That will be used to hold keys in the tree
index.
I have LeafNode template class derivered from TreeNode. That will be used to
hold keys and values in leaf.

Everything seems fine but it does not compile under MS.Net and gcc. It
compiles Dev-C++ but linker can not find Insert function and gives error.

I have checked many resources but I could not find the error. I would be
glad if you could explain me what is wrong.

Errors I get
TreeNode.h(5): error C2059: syntax error : '<' (The same line with
template)
TreeNode.h(5): error C2143: syntax error : missing '{' before '<' (The same
line with template)
TreeNode.c(3): error C2059: syntax error : '<'

main.c(9): error C2059: syntax error : 'type'

Code compiles fine here, but I cannot link because some files are
missing.

1) .c files are usually interpreted as being C files so your system may
compile them with a C compiler. Make them .cpp files.
2) most current compilers cannot compile templates if their member
functions are not defined inline (in the class). That`s probably why
dev-c++ is failing at link-time.


Jonathan
 
T

Tayfun Özdemir

Thank you so Jonathan. You were right. Some files were named "c" instead of
"cpp" :).

It compiles fine now. But I get linker error. I would be very glad if you
can explain what is wrong with my project. I have checked function
parameters and return value. They all match each other. I could not find the
error.

////// TreeNode.h ///////
////// TreeNode.h ///////
////// TreeNode.h ///////

#ifndef __TREE_NODE__
#define __TREE_NODE__


template <class KeyType, class ValType, int SIZE>
class TreeNode
{
public:
TreeNode() : nCount(0)
{};

virtual void Insert(KeyType Key, ValType Val, KeyType &ParentKey,
TreeNode<KeyType, ValType, SIZE> *&LeftChild,
TreeNode<KeyType, ValType, SIZE> *&RightChild);


protected:
int nCount;
KeyType e_Keys[SIZE];
TreeNode<KeyType, ValType, SIZE> *e_Childs[SIZE];
};

#endif




////// TreeNode.cpp ///////
////// TreeNode.cpp ///////
////// TreeNode.cpp ///////

#include "TreeNode.h"

template <class KeyType, class ValType, int SIZE>
void TreeNode<KeyType, ValType, SIZE>::Insert(KeyType Key, ValType Val,
KeyType &ParentKey,
TreeNode<KeyType, ValType, SIZE> *&LeftChild,
TreeNode<KeyType, ValType, SIZE> *&RightChild)
{
return;
}


////// LeafNode.h ///////
////// LeafNode.h ///////
////// LeafNode.h ///////

#include "TreeNode.h"

#ifndef __LEAF_NODE__
#define __LEAF_NODE__

template <class KeyType, class ValType, int SIZE>
class LeafNode : public TreeNode<KeyType, ValType, SIZE>
{
public:

LeafNode()
{
nCount = 0;
};


virtual void Insert(KeyType Key, ValType Val, KeyType &ParentKey,
TreeNode<KeyType, ValType, SIZE> *&LeftChild,
TreeNode<KeyType, ValType, SIZE> *&RightChild);



protected:
ValType e_Vals[SIZE];
};


#endif






////// LeafNode.cpp ///////
////// LeafNode.cpp ///////
////// LeafNode.cpp ///////

#include "LeafNode.h"

template <class KeyType, class ValType, int SIZE>
void LeafNode<KeyType, ValType, SIZE>::Insert(KeyType Key, ValType Val,
KeyType &ParentKey,
TreeNode<KeyType, ValType, SIZE> *&LeftChild,
TreeNode<KeyType, ValType, SIZE> *&RightChild)
{
int i = nCount;

// Shift values in the list by one until we find the spot
while (i != 0 && e_Keys[i - 1] > Key) {
e_Keys = e_Keys[i - 1];
e_Vals = e_Vals[i - 1];
i--;
}

// We are on the spot add new value to the list
e_Keys = Key;
e_Vals = Value;
nCount++;

// Check if we are full and are ready to split
if (nCount == SIZE) {
LeafNode<KeyType, ValType, SIZE> *Right = new LeafNode<KeyType,
ValType, SIZE>;

for (i = nCount / 2; i < nCount; i++) {
Right->e_Keys[i - nCount / 2] = e_Keys;
Right->e_Vals[i - nCount / 2] = e_Vals;
Right->nCount = i - nCount / 2 + 1;
}

}
return;
}






////// Main.cpp ///////
////// Main.cpp ///////
////// Main.cpp ///////

#include <cstdio>

#include "LeafNode.h"
#include "TreeNode.h"

int main(int argc, char *argv[])
{
int a;
LeafNode<int, int, 7> TestNode;
TreeNode<int, int, 7> *e, *f;


TestNode.Insert(10, 10, a, e, f);


return 0;
}





I really appreciate your help. Thanx for everything.
Sincerely.
Tayfun Özdemir.
 
J

Jonathan Mcdougall

Tayfun said:
Thank you so Jonathan. You were right. Some files were named "c" instead of
"cpp" :).

Please quote the message you are answering to.
It compiles fine now. But I get linker error. I would be very glad if you
can explain what is wrong with my project. I have checked function
parameters and return value. They all match each other. I could not find the
error.

As I said before, most current compilers cannot handle templates if
they don't have access to their definitions:

// c.h
template <class T>
class C
{
public:
T foo();
};

// c.cpp
# include "c.h"

template <class T>
T C<T>::foo()
{
// ...
}


// main.cpp
# include "c.h"

int main()
{
C<int> c;
c.foo();
}

The compiler usually has no problem with that, but the linker will not
be able to find the corresponding function. To solve this problem, make
the member function inline:

// c.h
template <class T>
class C
{
public:
T foo()
{
// ...
}
};

// c.cpp

// empty


See http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13 for
more informations. Read the whole faq while you're there.


Jonathan
 
T

Tayfun Özdemir

"Jonathan Mcdougall" <[email protected]>, haber iletisinde sunlari
yazdi:[email protected]...
Tayfun said:
Thank you so Jonathan. You were right. Some files were named "c" instead
of
"cpp" :).

Please quote the message you are answering to.
It compiles fine now. But I get linker error. I would be very glad if you
can explain what is wrong with my project. I have checked function
parameters and return value. They all match each other. I could not find
the
error.

As I said before, most current compilers cannot handle templates if
they don't have access to their definitions:

// c.h
template <class T>
class C
{
public:
T foo();
};

// c.cpp
# include "c.h"

template <class T>
T C<T>::foo()
{
// ...
}


// main.cpp
# include "c.h"

int main()
{
C<int> c;
c.foo();
}

The compiler usually has no problem with that, but the linker will not
be able to find the corresponding function. To solve this problem, make
the member function inline:

// c.h
template <class T>
class C
{
public:
T foo()
{
// ...
}
};

// c.cpp

// empty


See http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13 for
more informations. Read the whole faq while you're there.


Jonathan

-

Thank you so much again Jonathan. I read all of the FAQ and I tried both of
the suggestions on the FAQ. Unfortunately I could not solve my problem. I
will try to figure it out by trying something different.
Thanx for your replies.
Tayfun Özdemir.
 
J

Jonathan Mcdougall

[snipped badly quoted message]

http://web.presby.edu/~nnqadmin/nnq/nquote.html

Please, read it.
Thank you so much again Jonathan. I read all of the FAQ and I tried both of
the suggestions on the FAQ. Unfortunately I could not solve my problem. I
will try to figure it out by trying something different.

Perhaps we could help you more if you provided the error messages
generated with the code you provided in your previous post.


Jonathan
 
T

Tayfun Özdemir

"Jonathan Mcdougall" <[email protected]>, haber iletisinde
sunlari yazdi:[email protected]...
Thank you so much again Jonathan. I read all of the FAQ and I tried both
of
the suggestions on the FAQ. Unfortunately I could not solve my problem. I
will try to figure it out by trying something different.
Perhaps we could help you more if you provided the error messages
generated with the code you provided in your previous post.

Jonathan



I will change my newsreader very soon. Thanx for your reply.

I have changed my cpp and h files to their original.


I get following errors with different compilers:


////////////// .NET errors ////////////////

BTree error LNK2001: unresolved external symbol "public: virtual void
__thiscall TreeNode
<int,int,7>::Insert(int,int,int &,class TreeNode<int,int,7> * &,class
TreeNode<int,int,7> * &)" (?
Insert@?$TreeNode@HH$06@@UAEXHHAAHAAPAV1@1@Z)

BTree error LNK2019: unresolved external symbol "public: virtual void
__thiscall LeafNode
<int,int,7>::Insert(int,int,int &,class TreeNode<int,int,7> * &,class
TreeNode<int,int,7> * &)" (?
Insert@?$LeafNode@HH$06@@UAEXHHAAHAAPAV?$TreeNode@HH$06@@1@Z) referenced in
function _main


BTree fatal error LNK1120: 2 unresolved externals



////////////// gcc errors////////////////

[shootgun@plesk Tree]$ gcc LeafNode.cpp main.cpp TreeNode.cpp -o h
/tmp/ccnze0Bu.o(.text+0x3a): In function `main':
: undefined reference to `LeafNode<int, int, 7>::Insert(int, int, int&,
TreeNode<int, int, 7>*&,
TreeNode<int, int, 7>*&)'
/tmp/ccnze0Bu.o(.gnu.linkonce.d._ZTV8LeafNodeIiiLi7EE+0x8): undefined
reference to `LeafNode
<int, int, 7>::Insert(int, int, int&, TreeNode<int, int, 7>*&, TreeNode<int,
int, 7>*&)'
/tmp/ccnze0Bu.o(.gnu.linkonce.d._ZTV8TreeNodeIiiLi7EE+0x8): undefined
reference to `TreeNode
<int, int, 7>::Insert(int, int, int&, TreeNode<int, int, 7>*&, TreeNode<int,
int, 7>*&)'
/tmp/ccnze0Bu.o(.gnu.linkonce.d._ZTI8TreeNodeIiiLi7EE+0x0): undefined
reference to `vtable for
__cxxabiv1::__class_type_info'
/tmp/ccnze0Bu.o(.gnu.linkonce.d._ZTI8LeafNodeIiiLi7EE+0x0): undefined
reference to `vtable for
__cxxabiv1::__si_class_type_info'
/tmp/ccnze0Bu.o(.eh_frame+0x11): undefined reference to
`__gxx_personality_v0'
collect2: ld returned 1 exit status




I paste my files again. I am not sure if the last ones are correct.

////////////// TreeNode.h ////////////////
#ifndef __TREE_NODE__
#define __TREE_NODE__


template <class KeyType, class ValType, int SIZE>
class TreeNode
{
public:
TreeNode() : nCount(0)
{};

virtual void Insert(KeyType Key, ValType Val, KeyType &ParentKey,
TreeNode<KeyType, ValType, SIZE> *&LeftChild,
TreeNode<KeyType, ValType, SIZE> *&RightChild);


protected:
int nCount;
KeyType e_Keys[SIZE];
TreeNode<KeyType, ValType, SIZE> *e_Childs[SIZE];
};

#endif








////////////// TreeNode.cpp ////////////////

#include "TreeNode.h"

template <class KeyType, class ValType, int SIZE>
void TreeNode<KeyType, ValType, SIZE>::Insert(KeyType Key, ValType Val,
KeyType &ParentKey,
TreeNode<KeyType, ValType, SIZE> *&LeftChild,
TreeNode<KeyType, ValType, SIZE> *&RightChild)
{
return;
}







////////////// LeafNode.h ////////////////

#include "TreeNode.h"

#ifndef __LEAF_NODE__
#define __LEAF_NODE__

template <class KeyType, class ValType, int SIZE>
class LeafNode : public TreeNode<KeyType, ValType, SIZE>
{
public:

LeafNode()
{
nCount = 0;
};


virtual void Insert(KeyType Key, ValType Val, KeyType &ParentKey,
TreeNode<KeyType, ValType, SIZE> *&LeftChild,
TreeNode<KeyType, ValType, SIZE> *&RightChild);



protected:
ValType e_Vals[SIZE];
};


#endif






////////////// LeafNode.cpp ////////////////

#include "LeafNode.h"

template <class KeyType, class ValType, int SIZE>
void LeafNode<KeyType, ValType, SIZE>::Insert(KeyType Key, ValType Val,
KeyType &ParentKey,
TreeNode<KeyType, ValType, SIZE> *&LeftChild,
TreeNode<KeyType, ValType, SIZE> *&RightChild)
{
int i = nCount;

// Shift values in the list by one until we find the spot
while (i != 0 && e_Keys[i - 1] > Key) {
e_Keys = e_Keys[i - 1];
e_Vals = e_Vals[i - 1];
i--;
}

// We are on the spot add new value to the list
e_Keys = Key;
e_Vals = Val;
nCount++;

// Check if we are full and are ready to split
if (nCount == SIZE) {
LeafNode<KeyType, ValType, SIZE> *Right = new LeafNode<KeyType,
ValType, SIZE>;

for (i = nCount / 2; i < nCount; i++) {
Right->e_Keys[i - nCount / 2] = e_Keys;
Right->e_Vals[i - nCount / 2] = e_Vals;
Right->nCount = i - nCount / 2 + 1;
}

}
return;
}








////////////// main.cpp ////////////////

#include <cstdio>

#include "LeafNode.h"
#include "TreeNode.h"


int main(int argc, char *argv[])
{
int a;
LeafNode<int, int, 7> TestNode;
TreeNode<int, int, 7> *e, *f;


TestNode.Insert(10, 10, a, e, f);


return 0;
}



Thank you so much for your answers and patience.
Sincerely,
Tayfun Ozdemir
 
U

upashu2

Put your contents of .cpp files to corresponding .h files. They will
compile & link smoothly.
 
I

Ian

Tayfun said:
I have changed my cpp and h files to their original.


I get following errors with different compilers:
I think it has already been pointed out to you that some compilers (gcc
included) require template function bodies to be visible in the
compilation unit that uses them. I suggest you try including
TreeNode.cpp at the end of TreeNode.h, or just make life easy an inline
the function in the .h file.

Ian
 
T

Tayfun Özdemir

haber iletisinde sunlari said:
I think it has already been pointed out to you that some compilers (gcc
included) require template function bodies to be visible in the
compilation unit that uses them. I suggest you try including TreeNode.cpp
at the end of TreeNode.h, or just make life easy an inline the function in
the .h file.

Ian

You are absolutely right. I was told that I have to put them in somefile
where compiler can see them at compile time each time.
I just forgot about it :-(. Last time I used C++ was 3 years ago.

I really appreciate your efforts Ian, Jonathan and Upashu2.
Thanx for your replies.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top