Problem with templates

Hi,

after a lot of years of C-Sharp development I moved back to the good old c++ now.

One new feature that is new to me is templates and I run into some trouble with it as soon as I try to implement the functions of a templated class in a seperate file.

Working:
test.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifndef TEST_H
#define TEST_H

namespace neitzel
{
	template <typename T> class Test
	{
	public:
		Test();
		void Print();
	};

}

#endif // TEST_H 


main.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 "test.h"
using namespace std;
using namespace neitzel;

int main(int argc, char **argv)
{
	Test<int> *test = new Test<int>();
	test->Print();
	return 0;
}

namespace neitzel
{
	template <typename T> Test<T>::Test()
	{
	}

	template <typename T> void Test<T>::Print()
	{
		cout << "Hello World!" << endl;
	}
}


g++ main.cpp
./a.out
and I get my Hello world.

Now I remove the namespace neitzel { ... } part from main.cpp and simply put it inside test.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include "test.h"
using namespace std;

namespace neitzel
{
	template <typename T> Test<T>::Test()
	{
	}

	template <typename T> void Test<T>::Print()
	{
		cout << "Hello World!" << endl;
	}
}


and I try to compile it with
g++ main.cpp test.cpp
/tmp/ccEc8cEz.o: In function `main':
main.cpp:(.text+0x1d): undefined reference to `neitzel::Test<int>::Test()'
main.cpp:(.text+0x2d): undefined reference to `neitzel::Test<int>::Print()'
collect2: error: ld returned 1 exit status

I can remove the template stuff from the code and the compile works fine with the separation into multiple files ...

I think I am missing something easy and stupid - it would be great if you could help me on this issue.

With kind regards,

Konrad
Last edited on
Your class declared in namespace neitzel in .h file
Either remove namespace ftom there or put it into ypur cpp file
Thank you for your reply.

I used the namespace inside the .h and .cpp file. So even inside the .cpp files I used the namespace neitzel. (Only the main function is not inside a defined namespace!)

And removing the namespace does not change anything - just the error message complains about Test<int>::Test() instead of neitzel::Test<int>::Test()

With kind regards,

Konrad
!!!
Does your new cpp file included in compile list? It looks like it just isn't linked.
Hi,

again thank you for your reply.

Yes, it is inside the compile list. I double checked it in 2 ways:

1) I am not using any IDE any longer to prevent problems with any project management. So I really call
g++ main.cpp test.cpp
(So both .cpp files are used)

2) I did the test without any templates used. And a call to g++ main.cpp test.cpp worked fine and everything was linked together successfully and the implementation of the method inside test.cpp was linked together successfully.

Maybe it helps if I tell you my build environment:
I am unsing an opensuse 12.3 with
g++ (SUSE Linux) 4.7.2 20130108 [gcc-4_7-branch revision 195012]

And on Windows 7 with DevLite 5.2 I get the same result.

I will try to edit my first post so that the source is easier to read.

With kind regards,

Konrad
Ok. I got it. Problem is, when compiler compiles your test.cpp, he does not know that he should generate code for <int> template type.
There is ways to force it to do that, but the bes one is to just move templates definitions into header. That way thet are used in standard library.

I didn't find thread where it explained fully, but there is some info:
http://stackoverflow.com/questions/36039/templates-spread-across-multiple-files
http://stackoverflow.com/questions/4496440/multiple-file-template-implementation
Ahh great! These links helped!

I moved the implementation of the methods that include templates into the header file and it works.

I just tested it with 2 files that both include the .h file and create a Test<int> instance to see if I get warnings or errors like "neitzel::Test<int>::Test() is already implemented" - but I didn't get such an error so I have a solution right now.

And I will do more tests with the extern keyword to see if I can find a solution that looks cleaner. (I like the idea to keep the implementation separate of the definition.)

Thank you very much for your quick and great help! You gave me links that I tried to find with google for half a day.

With kind regards,

Konrad
For use of extern you should know in advance template parameters which will be used. Which kinda defeats purpose of templates.
Placing template definitions in headers is reccomended way to do it. All standard library works this way and Aleksandresku advises to use them that way.
Topic archived. No new replies allowed.