Need help with class templates.

Hello.

I an new to class templates. I am trying to define class Point. Right now Point only has member coords to store coordinates in list. I am trying to make class that would work with any dimensional space. For 1 dimensional space, coords list should have size of 1. For 2D coords.size() should be 2 and so on. For this I tried to use template, but I did something wrong, and I dont know what.

background info: Previously, I had class Point2 for point 2D point (x, y). And Point3 for 3D point (x,y,z). Now need to generalize it so it woul work with any number of dimensions.

point.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef POINT_H
#define POINT_H


#include <iostream>
#include <list>
using std::ostream;


template <unsigned short n>
class Point {

public:
	std::list<float> coords (n);

	Point() = default; //c++11 The default constructor is explicitly stated.

	Point(std::list<float> p);

	float distanceFrom (std::list<float> p);
};

#endif 


point.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "point.h"
#include <math.h>       /* sqrt */
#include <list>


Point::Point(std::list<float> arg)
{
	coords.assign (arg.begin(), arg.end());
}


float Point::distanceFrom (Point p) {
	//return sqrt (pow(x-p.x,2.0) + pow(y-p.y,2.0));
	return 0.0;
}


test.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
#include <cstdlib>
#include <list>
#include "point.h"

using namespace std;

int main (int argc, char* argv[]) {
	Point<2> v1;
	cout << v1.coords.size() << endl;

	return EXIT_SUCCESS;
}


errors
1
2
3
4
D:\Dropbox\cpp\point.h|14|error: 'n' is not a type|
D:\Dropbox\cpp\test.cpp||In function 'int main(int, char**)':|
D:\Dropbox\cpp\test.cpp|10|error: 'v1.Point<n>::coords<2u>' does not have class type|
||=== Build failed: 2 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|


what do I need to do that cout << v1.coords.size() << endl; would print 2 (test.cpp should not be changed)? How do I use that n inside class?
Last edited on
point.h (test.cpp remains untouched, point.cpp dissapears)
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
#ifndef POINT_H
#define POINT_H


//#include <iostream> //not being used
#include <list>
//using std::ostream; //never do `using' in headers


template <unsigned short n>
class Point {

public:
	std::list<float> coords = std::list<float>(n); //initialization

	Point() = default; //c++11 The default constructor is explicitly stated.

	Point(std::list<float> p);

	//float distanceFrom (std::list<float> p); //it does not match with your definition
	float distanceFrom (Point p);
};

//still in point.h, you can't separate template definitions

#include <math.h>       /* sqrt */
#include <list>


template <unsigned short n> //Point is a template
Point<n>/*here too, need to especify the template parameter*/::Point(std::list<float> arg)
{
	coords.assign (arg.begin(), arg.end());
}


template <unsigned short n> //Point is a template
float Point<n>::distanceFrom (Point p) { //no need to especify, but its argument has the same template parameter (Point<n>)
	//return sqrt (pow(x-p.x,2.0) + pow(y-p.y,2.0));
	return 0.0;
}

#endif 



> store coordinates in list.
that's like the worst container that you may chose.
consider std::{array,valarray,vector} where you also have random access.
Last edited on
Thanks.

I dont understand one thing. If I use your code, everything works but as soon as I use separate header and code files, it breaks.

point.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef POINT_H
#define POINT_H


#include <iostream>
#include <list>
using std::ostream;


template <unsigned short n>
class Point {

public:
	std::list<float> coords = std::list<float>(n); //initialization

	Point() = default; //c++11 The default constructor is explicitly stated.

	Point(std::list<float> p);

	float distanceFrom (Point p);
};

#endif


point.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "point.h"
#include <math.h>       /* sqrt */
#include <list>

template <unsigned short n> //Point is a template
Point<n>::Point(std::list<float> arg)
{
	coords.assign (arg.begin(), arg.end());
}


template <unsigned short n>
float Point<n>::distanceFrom (Point p)  {
	//return sqrt (pow(x-p.x,2.0) + pow(y-p.y,2.0));
	return 0.0;
}


test.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <cstdlib>
#include <list>
#include "point.h"

using namespace std;

int main (int argc, char* argv[]) {
	Point<2> v1;
	// Require member coords
	cout << v1.coords.size() << endl;
	// Require constructor with parameters
	Point<2> v2 { list<float>{} };
	// Require distanceFrom method
	//float f = v1.distanceFrom(v1);
	// Require toString method
	//cout << v1.toString () << endl;
	// Require << operators
	//cout << v1 << endl;


	return EXIT_SUCCESS;
}


Error (about Point<2> v2 { list<float>{} };):
undefined reference to `Point<(unsigned short)2>::Point(std::list<float, std::allocator<float> >)'|

Last edited on
Your point.h looks a bit off.
Tnx, I pasted wrong code here. I edited post now.
http://www.cplusplus.com/forum/general/113904/#msg622073


By the way
1
2
3
4
5
6
7
template <unsigned short n>
Point<n>::Point(std::list<float> arg)
{
	coords.assign (arg.begin(), arg.end()); //you need to make sure that arg.size()==n
}

Point<2> v2 { list<float>{} }; //v2.coords is empty instead of having 2 elements 
Last edited on
But that same line of code worked with your code. I dont get it why does it work with yours but not with mine...
Last edited on
If I use your code, everything works but as soon as I use separate header and code files, it breaks.

That's because when dealing with templates the definition and implementation must be in the same compilation unit. This quite often leads to header only implementations, or including the source in the header.

Ok. I did not know that. It came as a little surprise to me because it is actually a task from C++ course where we were told to have separate .cpp and .h files. And that's why I told above not to change test.cpp... test.cpp was actually provided by lectures and we are supposed to write the rest of the code so that test.cpp compiles as compiles as they have provided it. All that I did for this topic was removing code from the end to make it shorter.


My intention is just to get to know it a little bit before course starts and solve few simpler problems in advance that it would be easier to follow.
Last edited on
Topic archived. No new replies allowed.