template function definitions in header files

hi friends,

so its Friday evening and i was wondering what i should do, so i decided to write some code and i ended up trying to design my own little helper collection. (u know some nice stuff u need from time to time .. )

so lets be creative and call the file helper.h/cpp !
to demonstrate my problem i need 2 more files. let one be main.cpp and the other a class encapsulating human beings: human.h/cpp

so here i go:
main.cpp
1
2
3
4
5
6
7
8
#include "human.h"
#include "helper.h"

int main()
{
   toString(6);
   return 0;
}


human.h
1
2
3
4
5
6
7
8
#ifndef _HUMAN_H
#define _HUMAN_H

#include <string>

std::string getName();

#endif 


human.cpp
1
2
3
4
5
6
7
8
9
10
#include "human.h"
#include "helper.h"

#include <string>

std::string getName()
{
   //and my creativity goes on ..
   return toString(28);
}


helper.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#ifndef _HELPER_H
#define _HELPER_H

#include <string>
#include <sstream>
#include <iostream>
   
//number --> string
template<class Numeric>
std::string toString(Numeric num)
{
   std::ostringstream stream;
   stream << num;
   return stream.str();
}

#endif 



ok i summarize what we have got here:
there is my helper file which offers the toString function. the helper file is included in both main.cpp and widget.cpp. consequently the toString function is declared and defined in both, which should cause a linking problem, because defining the same function twice is generally a bad idea.
but this code is fine, it compiles and runs .. and confuses me a little ;)

the problem:
lets add this single line to helper.h:
void foo() {}
now it wont compile anymore, because the same non template function is defined twice, which is a problem for my compiler (poor guy).

and now my question:
i know how to solve this problem .. i just need to move the definition of foo to helper.cpp which is no problem ..
but i am not quite sure why this stuff is working with template functions? is it because the compiler adds kind of a unique id to the template function when it creates the code for the template function or how does this work?

i hope u guys are able to understand my problem .. i really tried to make this clear and understandable, but if there are question on my question pleas ask me. well and thanks for your help =)

lg,
flowly
It is because a template function is not actually a function. Instead, it is a "template" (heh) for a function that the compiler uses at compile time to make functions. Because of this, you must have the entire body/definition of the function present when you want to use it. Normally, as you say, this would cause a linker error, however since they require the entire body to be present in order to even use it (instead of just a prototype), compilers will not generate linker errors because of that.
hi firedraco,

thank u for your fast answer !

ok, right. but i would really like to understand how it is working and not just that its working or why it has to work this way .. lets look at the two processes (compiling and linking) individual:

g++ -c -o main.o main.cpp
the compiler will see the template code (from include "helper.h") and store it to be able to produce real code later.
1
2
3
4
5
6
7
template<class Numeric>
std::string toString(Numeric num)
{
   std::ostringstream stream;
   stream << num;
   return stream.str();
}


then the compiler goes on and finds a function call to the template code:
 
toString(6);

now the compiler produces the actual code for the function for integers.
1
2
std::string toString(int num)
{ ... }

and then the compiler is ready with main.cpp and has to store the produced code in the object file, including the code it produced for the template function.

g++ -c -o human.o human.cpp
so here the same thing happens again. it does not know anything about the code it has produced for main.o, consequently it will produce the same function code again, doesn't it?

=> i have two object files containing the same function, am i wrong ? the code has to be produced write now because we are ready with compiling and start linking:


g++ -o test main.o human.o
now the linker will see that there is a "std::string toString(int num);" function defined in both files, why doesn't he care (at this point it has to be an actual function, because the linker cant build one, its just a linker ..)? he doesn't know that these are templetes and even if he would know .. he still wouldn't know which function call he should link to which function implementation, would he?

u see my point? i dont understand how the linker can differ between these function because as far as i know after compilation a template is transformed to a "normal function"? please tell me which step in my little story is the broken one?

lg,
flowly
Compilers (and linkers) are smart. It knows it defined it already so it reuses the definition. Just think of defining a function in one.cpp and declaring the prototype in two.cpp, three.cpp, four.cpp, etc.
Last edited on
that's right - compilers, in respect to templates, have a policy of compile on use

if template code, down to the function level, is not used anywhere, it will actually not be compiled into any binary at all
ok thanks guys =)

@L B: the comparison helped me :)
Topic archived. No new replies allowed.