Since when do template get multiply defined errors?

I've made some templated functions for converting stuff to/from strings using
stringstreams in a header file that is included in several cpp files, and my
linker is giving me errors for them being multiply defined! I thought templates
could be multiply defined because of the compiler's compile-on-use policy?
Why does the linker care about templates?

Here is the header in its entirety:
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
51
52
53
54
#ifndef _StringConverter_HeaderPlusPlus_
#define _StringConverter_HeaderPlusPlus_
#ifdef _STRING_
#include <sstream>
using namespace std;

template<typename T>
string Str(const T& from)
{
	ostringstream ss;
	ss << from;
	return(ss.str());
}
template<>
string Str<signed char>(const signed char& from)
{
	ostringstream ss;
	ss << signed short(from);
	return(ss.str());
}
template<>
string Str<unsigned char>(const unsigned char& from)
{
	ostringstream ss;
	ss << unsigned short(from);
	return(ss.str());
}

template<typename T>
T Num(const string& from)
{
	istringstream ss (from);
	T temp;
	ss >> temp;
	return(temp);
}
template<>
signed char Num<signed char>(const string& from)
{
	istringstream ss (from);
	signed short temp;
	ss >> temp;
	return(signed char(temp));
}
template<>
unsigned char Num<unsigned char>(const string& from)
{
	istringstream ss (from);
	unsigned short temp;
	ss >> temp;
	return(unsigned char(temp));
}
#endif //_STRING_
#endif //_StringConverter_HeaderPlusPlus_ 

And here are the linker's angry errors:
1>Linking...
1>General.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Str<signed char>(signed char const &)" (??$Str@C@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABC@Z) already defined in Edittime.obj
1>General.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Str<unsigned char>(unsigned char const &)" (??$Str@E@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABE@Z) already defined in Edittime.obj
1>General.obj : error LNK2005: "signed char __cdecl Num<signed char>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$Num@C@@YACABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Edittime.obj
1>General.obj : error LNK2005: "unsigned char __cdecl Num<unsigned char>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$Num@E@@YAEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Edittime.obj
1>Main.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Str<signed char>(signed char const &)" (??$Str@C@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABC@Z) already defined in Edittime.obj
1>Main.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Str<unsigned char>(unsigned char const &)" (??$Str@E@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABE@Z) already defined in Edittime.obj
1>Main.obj : error LNK2005: "signed char __cdecl Num<signed char>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$Num@C@@YACABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Edittime.obj
1>Main.obj : error LNK2005: "unsigned char __cdecl Num<unsigned char>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$Num@E@@YAEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Edittime.obj
1>Runtime.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Str<signed char>(signed char const &)" (??$Str@C@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABC@Z) already defined in Edittime.obj
1>Runtime.obj : error LNK2005: "class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Str<unsigned char>(unsigned char const &)" (??$Str@E@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@ABE@Z) already defined in Edittime.obj
1>Runtime.obj : error LNK2005: "signed char __cdecl Num<signed char>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$Num@C@@YACABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Edittime.obj
1>Runtime.obj : error LNK2005: "unsigned char __cdecl Num<unsigned char>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &)" (??$Num@E@@YAEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) already defined in Edittime.obj
1>   Creating library .\Release/rsdk.lib and object .\Release/rsdk.exp
1>C:\Program Files\Multimedia Fusion Developer 2\Extensions\TestObject.mfx : fatal error LNK1169: one or more multiply defined symbols found
Last edited on
I think it's the specializations.
So, specializations can't be multiply defined...? Well, I'll have to work around that somehow...thanks.
specializations can't be multiply defined

As far as the linker is concerned, I would have thought that template specialisations are just the same as normal functions (I may be wrong though).

As long as they stay that small, you could just make them inline (though I don't see why putting them in a cpp file would be a problem...)
Last edited on
Thanks, though I ended up making them static member functions of a templated and specialized class, so I can just do ConvertTo<signed char>::Num("120");
It's not the most elegant solution but it still works for me.
Last edited on
Topic archived. No new replies allowed.