Unresolved External error in multiple file program

Hi,
Im learning C++ through 'The C++ Language Tutorial' by Juan Soulie and Ive reached the chapter on Template Functions. I've written up the example in visual studio 2008 and it works just fine.
I tried to modify the example by using multiple files and simply introducing a new template function in a separate .cpp file with its own header file that includes a prototype for that template function. If I try to call that funtion from my main() function I get an unresolved external link error with that function call.
If I omit that function then the program compiles and runs. If I copy and paste the template function above main then it compiles and runs just fine. I experimented and if I make the function a dedicated float function (getting rid of the template) in the secondary file then the program compiles and runs just fine. It is only when the secondary file has a template function then I get the external link error.
I would like to understand why this happens and how to correct this so that I can have a template function in a multiple file program. Here is my main code in the sources folder:

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
// function template

#include <iostream>
#include "functions.h"

using namespace std;


template <class T>
T GetMax(T a, T b) 
{
	T result;
	result = (a>b) ? a : b;
	return result;
}

int main()
{
	int i = 5, j = 6, k;
	long l = 10, m = 5, n;
	float x = 10.43, y = 5.55, z;

	k = GetMax(i, j);
	n = GetMax <long> (l, m);
	z = GetMax(x, y);

	cout << k << endl;
	cout << n << endl;
	cout << z << endl;

	cout << addValues(x, y) << endl;

	cout << Subtract(x, y) << endl;

	return 0;

}


the functions.h file in the header files folder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

#ifndef FUNCTIONS
#define FUNCTIONS

#include <iostream>
using namespace std;


float addValues(float a, float b);

template <class Type>
Type Subtract(Type a, Type b);


#endif 


and the function.cpp file in the sources file folder:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include "functions.h"

using namespace std;


 float addValues(float a, float b)
{
	return (a+b);
}

 template <class Type>
 Type Subtract(Type a, Type b)
 {
	 Type result;
	 result = (a - b);

	 return result;
 }


And here is the error (i ommited the truncation warnings from double to float for the first two float initialisations)

error LNK2019: unresolved external symbol "float __cdecl Subtract<float>(float,float)" (??$Subtract@M@@YAMMM@Z) referenced in function _main
1>I:\Files\Projects\Visual Studio Projects\C++ Online Tutorials\Chapter - Templates\Function Template\Debug\Function Template.exe : fatal error LNK1120: 1 unresolved externals
closed account (yUq2Nwbp)
i think i understand.......in your main.cpp you include only functions.h in which you didn't include your function.cpp..........replace #include<functions.h> with #include<functions.cpp> because your functions.cpp contains function.h....
Im afraid that didnt work I get the same error plus a new one:
1>functionTemplate.obj : error LNK2005: "float __cdecl addValues(float,float)" (?addValues@@YAMMM@Z) already defined in functions.obj

Plus the function addValues in function.cpp is able to be linked to the main() function just fine it is only Subtract that gives me a linking problem. For example if I change function.cpp so it looks like this:
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
#include <iostream>
#include "functions.h"

using namespace std;


 float addValues(float a, float b)
{
	return (a+b);
}

/* template <class Type>
 Type Subtract(Type a, Type b)
 {
	 Type result;
	 result = (a - b);

	 return result;
 }*/

float Subtract(float a, float b)
 {
	 float result;
	 result = (a - b);

	 return result;
 }


and my functions.h to look like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef FUNCTIONS
#define FUNCTIONS

#include <iostream>
using namespace std;


float addValues(float a, float b);

float Subtract(float a, float b);

//template <class Type>
//Type Subtract(Type a, Type b);


#endif 


then the code works as intended.
Only when I use a template function in functions.cpp do I get the aforementioned linking error.
david91 wrote:
in your main.cpp you include only functions.h in which you didn't include your function.cpp
I can't quote scripture on this but I'm sure that including a .cpp file is not a reccomended practice. You are supposed to only include .h files, although feel free to correct me if I'm wrong :)

@OP: This is a quote taken from the documentation regarding Templates from this site, which can be found at the bottom of the following page: http://www.cplusplus.com/doc/tutorial/templates/

Because templates are compiled when required, this forces a restriction for multi-file projects: the implementation (definition) of a template class or function must be in the same file as its declaration. That means that we cannot separate the interface in a separate header file, and that we must include both interface and implementation in any file that uses the templates.
For a more detailed answer read the documentation provided above.

Also I'm not too sure what you are trying to accomplish by separating these functions into a separate file. Normally you use separate files to try make the code more manageable and clear, however this has not been the outcome here.

Another by product you also seem to have multiple #include <iostream> pre-processor calls and using calls that could be avoided.

I hope this helps!
Last edited on
Thanks for the information Ink2019 this answers the question, Template functions just cannot be used in multiple files. They have to remain in the files that use/call them.

I know that the separate files I used did not make the code more manageable and clear I was only doing it this way to learn how multiple files work and as a consequence, why templates didnt work in multiple files.

I did include iostream and using in functions.cpp and functions.h just to rule out anything I may have missed that was giving the linking error.

I actually have that same documentation in the tutorials that I'm learning from, I guess I just got ahead of myself and tried to do something that the book would later tell me can't be done.


Topic archived. No new replies allowed.