I downloaded a generic AVL implementation from: http://sourceforge.net/projects/standardavl/files/standardavl/0.1/
The makefile in this project compiles correctly the code. The compiler produces the follow output:
g++ -pedantic -Wall -O3 -c standardavl.cpp -o standardavl.o
g++ -pedantic -Wall -O3 -c Point.cpp -o Point.o
g++ -o standardavl standardavl.o Point.o
g++ -o genpoints genpoints.o Point.o
The makefile compiles only "standardavl.cpp", because standartavl includes "AvlTree.h" and this file includes "AvlTree.cpp":
standardavl.cpp
#include "AvlTree.h"
#include "Point.h"
(...)
AvlTree.h
(...)
#include "AvlTree.cpp"
In my project I removed the last line (#include "AvlTree.cpp") from the file AvlTree.h and compiled individually that files. I do not use the file "standardavl.cpp" also. I changed the file Point.h to KeyPair.h and implemented all operators there.
My compiler produces the follow output:
g++ -pedantic -Wall -O3 -c -o ../lib/CPUTimer.o ../lib/CPUTimer.cpp -I. -I../lib
g++ -pedantic -Wall -O3 -c -o ../lib/AvlTree.o ../lib/AvlTree.cpp -I. -I../lib
g++ -pedantic -Wall -O3 -c -o ../lib/keypair.o ../lib/keypair.cpp -I. -I../lib
g++ -pedantic -Wall -O3 -c -o graph.o graph.cpp -I. -I../lib
g++ -pedantic -Wall -O3 -c -o dijkstra.o dijkstra.cpp -I. -I../lib
g++ -pedantic -Wall -O3 -o ../../q1 ../lib/CPUTimer.o ../lib/AvlTree.o ../lib/keypair.o graph.o dijkstra.o questao1.cpp -I. -I../lib
dijkstra.o: In function 'Dijkstra::executeAvl(int)':
dijkstra.cpp:(.text+0x25d): undefined reference to 'AvlTree<KeyPair, std::less<KeyPair>, nil<KeyPair> >::AvlTree()'
(... a lot of errors like above ...)
collect2: ld returned 1 exit status
make[1]: ** [q1] Erro 1
What I am doing wrong here?
Assuming AvlTree.h declares a template class AvlTree<>
, and AvlTree.cpp defines the implementation:
You can't define the implementation of template code in a separate translation unit (.cpp) -- it must exist where it is used. That's why they included it in the header. Putting the implementation in a .cpp file to be included was just a design choice to keep the .h file concise.
(Well, technically you can put the template definition in a separate translation unit, but you must explicitly instantiate it for the template arguments you'll be using. I'm guessing that's not what you want to do.)