Reputation: 7209
I have a class named "SimObject":
namespace simBase
{
class __declspec(dllexport) SimObject: public SimSomething
{
public:
template <class T>
void updateParamValue( const std::string& name, T val );
}
}
I have another class named "ITerrainDrawable":
namespace simTerrain
{
class __declspec(dllexport) ITerrainDrawable : public simBase::SimObject
{
}
}
These classes are in different libraries. SimObject is in simBase, ITerrainDrawable is in simTerrain libraries. Even if ITerrainDrawable is derived from SimObject and I included library of simBase, I get a link error:
unresolved external symbol
1>ITerrainDrawable.obj : error LNK2019: unresolved external symbol "public: void __thiscall simBase::SimObject::updateParamValue<float>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,float)" (??$updateParamValue@M@SimObject@simBase@@QAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@M@Z) referenced in function "public: void __thiscall simTerrain::ITerrainDrawable::setTerrainSize(float)" (?setTerrainSize@ITerrainDrawable@simTerrain@@QAEXM@Z)
1>ITerrainDrawable.obj : error LNK2019: unresolved external symbol "public: void __thiscall simBase::SimObject::updateParamValue<class osg::Vec4f>(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class osg::Vec4f)" (??$updateParamValue@VVec4f@osg@@@SimObject@simBase@@QAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@VVec4f@osg@@@Z) referenced in function "public: void __thiscall simTerrain::ITerrainDrawable::setSatelliteTextureBorders(class osg::Vec2f,class osg::Vec2f)" (?setSatelliteTextureBorders@ITerrainDrawable@simTerrain@@QAEXVVec2f@osg@@0@Z)
Why do I get this error?
Everything works fine if I don't use template function but I need it.
If I move this function to simTerrain library it works fine but I don't want to use duplicate function because there are many libraries like simTerrain.
Upvotes: 9
Views: 18434
Reputation: 25098
You need to specify (cpp file is fine) template specialization. It means you need to export all combination of template arguments, you are going to use:
template __declspec(dllexport) void updateParamValue<int>( const std::string& name, T val );
template __declspec(dllexport) void updateParamValue<short>( const std::string& name, T val );
......
I use this in Visual Studio 2013 and it works.
Upvotes: 5
Reputation: 181
Here is the working example:
template<class T> TEST_API void foo(T)
{
std::cout << "test";
}
template TEST_API void foo(int);
template TEST_API void foo(char);
Dump of file test.dll
File Type: DLL
Section contains the following exports for test.dll
00000000 characteristics
4FDEF629 time date stamp Mon Jun 18 12:34:33 2012
0.00 version
1 ordinal base
3 number of functions
3 number of names
ordinal hint RVA name
1 0 00001032 ??$foo@D@@YAXD@Z = @ILT+45(??$foo@D@@YAXD@Z)
2 1 00001014 ??$foo@H@@YAXH@Z = @ILT+15(??$foo@H@@YAXH@Z)
Upvotes: 4
Reputation: 92854
The full implementation of a template class must be in that template class's header. The ANSI/ISO standards for C++ allow for a way to put the implementation in a separate compilation unit using the export keyword , but there are currently any compilers that actually support this.
For more information read this and this.
Upvotes: 5
Reputation: 8529
There are two compilation model for templates :
You can use export keyword at time of template definition for 2nd option.
export template <class T>
void updateParamValue( const std::string& name, T val ) {}
But I am not sure that all compiler supports it.
Upvotes: 5
Reputation:
C++ does not really support the separate compilation of template code - you need to put the definition of the template in a header file.
Upvotes: 16