File separation w/ templates & structs

Hello,

I'm using
Mac OS X version 10.6.5
Xcode version 3.2.5

I've been using c++ independently for years, but I'm just starting out separating files. I've tested all the code below and it has "worked perfectly" (passes unit tests) when in a single file. I have the following

1) A sorter
2) A (geometric) vector struct
3) A "functional sorter" (fSort) that sorts elements by some function of the elements.

I have included 1, then 2 successively. I am now trying to include 3.

I'm getting the following error

"void sort<fSort_group<vec, double> >(fSort_group<vec, double>*, int)", referenced from:
Void fSort<vec, double>(vec*, int, double (*)(vec))in fSort.o
Symbol(s) not found

I think I'm including everything I should be. My structure looks like what I've seen in example templates. Could someone more experienced with separation of code into multiple files help?

Thank you in advance.


(If requested, I will post the entire files, but I think the post grows long already)

sort.h:
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef SORT_H
#define SORT_H

template <class T>
void sort(T *,int);
template <class T>
void _sort(T *,int,T,T);
void sortRunUnitTests();
template <class T>
void sortTest(T *,int);

#endif 

sort.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "sort.h"
#include <iostream>
#include <algorithm>
#include <time.h>
#include "core.h"
#include "probability.h"

template <class T>
void sort(T *L, int len) {
...	_sort<T>(L+i,len-1-i,min,max);
...}

template <class T>
void _sort(T *L, int len, T min, T max) {
...	_sort(L,i-1,min,pivot);
...	_sort(L+i,len-i,pivot,max);
...}

void sortRunUnitTests() {
	int N = 0x200000; int *L; L = new int[N];
	std::cout<<"Random:  ";for(int c=0;c<N;c++){L[c]=dice(0x8000000);} sortTest(L,N);
...}

template <class T>
void sortTest(T *L, int len) {
	T *L2; L2 = new T[len]; for (int c=0;c<len;c++) {L2[c]=L[c];}
	clock_t t1 = clock(); std::sort(L,L+len); t1 = clock()-t1;
	clock_t t2 = clock(); sort(L2,len);  t2 = clock()-t2;
	for (int c=0;c<len;c++) { if(L[c]!=L2[c]) { std::cout << " FAIL\n"; return; } }
	if (t1<t2) { std::cout << " SLOW (" << t1 <<" vs "<<t2<<")\n"; return; }
	std::cout << " FAST (" << t1 <<" vs "<<t2<<")\n";
}

vec.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef VEC_H
#define VEC_H
#include <math.h>
struct vec {
	double x,y,z;
	inline vec(double a=0, double b=0, double c=0) {
		x=a; y=b; z=c;
	}
	inline vec clone();
	inline vec operator + (vec);
	inline vec operator - (vec);
	inline vec operator * (double);
	...
};

inline vec vec::clone() {...}
inline vec vec::operator + (vec v) {...}
inline void vec::operator += (vec v) {...}
inline vec vec::operator - (vec v) {...}
...

#endif 

vec.cpp:
 
#include "vec.h" 

fSort.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef FSORT_H
#define FSORT_H

#include "sort.h"
#include "vec.h"

template <class T, class fnResult>
void fSort(T *, int, fnResult (*)(T));
void fSortRunUnitTests();
template <class T, class fnResult>
void fSortTest(T *, int, fnResult (*)(T));

#endif 

fSort.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream>
#include "fSort.h"

template <class T, class fnResult>
struct fSort_group {
	T item;
	fnResult v;
	fSort_group(T *base = new T, fnResult val = 0) {
		item = *base;
		v = val;
	}
	inline bool operator < (fSort_group g) { return v < g.v; }
	inline bool operator > (fSort_group g) { return v > g.v; }
	inline bool operator <= (fSort_group g) { return v <= g.v; }
	inline bool operator >= (fSort_group g) { return v >= g.v; }
	inline bool operator == (fSort_group g) { return v == g.v; }
	inline bool operator != (fSort_group g) { return v != g.v; }
};

template <class T, class fnResult>
void fSort(T *L, int len, fnResult (*fn)(T)) {
	fSort_group <T, fnResult> newL[len];
	for (int c = 0; c < len; c++) {
		newL[c] = fSort_group<T, fnResult>(L+c, fn(L[c]));
	}
	sort(newL, len);
	for (int c = 0; c < len; c++) {
		L[c] = newL[c].item;
	}
};

double fSortRunUnitTests_vectorMagnitude(vec v) { return v.p(); }

void fSortRunUnitTests() {
	int len = 100000; vec *L; L = new vec[len];
	for (int c = 0; c < len; c++) {
		L[c] = vec((c*1051)%2000000-(1000000),
				   (c*5867)%2000000-(1000000),
				   (c*6029)%2000000-(1000000)); }
	std::cout << "fSort:";
	fSortTest(L, len, fSortRunUnitTests_vectorMagnitude);
}

template <class T, class fnResult>
void fSortTest(T *L, int len, fnResult (*fn)(T)) {
	fSort<T,fnResult>(L,len,fn);
	for (int c = 0; c < len-1; c++) {
		if (fn(L[c]) > fn(L[c+1])) { std::cout << " FAIL\n"; return; } }
	std::cout << " PASS\n";
}

template functions/classes have to be defined in the headers.
unless you are only going to use them in one cpp..
the point is that the definition must be 'visible' from every place where it is used.
Topic archived. No new replies allowed.