2009-12-28 69 views
8

我有一个名为 “SimObject” 一类:无法导出模板功能

namespace simBase 
{ 
    class __declspec(dllexport) SimObject: public SimSomething 
    { 
     public: 

      template <class T> 
      void updateParamValue(const std::string& name, T val); 
    } 
} 

我有一个名为 “ITerrainDrawable” 其他类:

namespace simTerrain 
{ 
    class __declspec(dllexport) ITerrainDrawable : public simBase::SimObject 
    { 
    } 
} 

这些类不同的库。 SimObject在simBase中,ITerrainDrawable在simTerrain库中。即使ITerrainDrawable从SimObject衍生和我包括simBase的图书馆,我得到一个链接错误:

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)" ([email protected]@[email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]) referenced in function "public: void __thiscall simTerrain::ITerrainDrawable::setTerrainSize(float)" ([email protected]@[email protected]@[email protected]) 
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)" ([email protected]@[email protected]@@[email protected]@@[email protected][email protected]@[email protected]@[email protected]@[email protected]@[email protected]@[email protected]@@@Z) referenced in function "public: void __thiscall simTerrain::ITerrainDrawable::setSatelliteTextureBorders(class osg::Vec2f,class osg::Vec2f)" ([email protected]@[email protected]@[email protected]@@[email protected]) 

为什么我得到这个错误?

一切工作正常,如果我不使用模板功能,但我需要它。

如果我将这个函数移动到simTerrain函数库中,它工作正常,但我不想使用重复函数,因为有许多类似simTerrain的函数库。

回答

10

C++并不真的支持单独编译模板代码 - 您需要将模板的定义放在头文件中。

+0

谢谢尼尔:)它工作时,我将函数定义的标题 – ufukgun 2009-12-28 13:02:18

5

模板类的完整实现必须位于该模板类的标题中。 C++的ANSI/ISO标准允许使用export关键字将实现放在单独的编译单元中,但目前有实际上支持这一点的编译器。

有关详细信息读thisthis.

+0

我使用VisualStudio2008和响应导出是:警告C4237:'导出'关键字尚未支持,但保留供将来使用 – ufukgun 2009-12-28 14:20:11

6

存在用于模板两个编译模型:

  1. 夹杂编译模型(如包括头文件)
  2. 独立编译模型从实现的接口(分离)

您可以使用导出关键字第二个选项的模板定义时间。

export template <class T> 
void updateParamValue(const std::string& name, T val) {} 

但我不确定所有的编译器都支持它。

+0

我使用VisualStudio2008并且对导出的响应是: 警告C4237:'导出'关键字尚未支持,但保留供将来使用 – ufukgun 2009-12-28 14:20:47

+0

vC++ 7.0不支持它,可能是下一版本可能会支持它。 但我运行在支持它的linux GNU C++ 8.2编译器上。 – Ashish 2009-12-29 06:14:35

+0

我希望你的回答是真实的,但愚蠢vs不支持它:/ 我不喜欢写函数定义到标题。 – ufukgun 2009-12-29 08:06:30

4

这里是工作示例:

template<class T> TEST_API void foo(T) 
{ 
    std::cout << "test"; 
} 

template TEST_API void foo(int); 
template TEST_API void foo(char); 

Test.dll文件的转储

文件类型:DLL

段包含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 [email protected]@@[email protected] = @ILT+45([email protected]@@[email protected]) 
     2 1 00001014 [email protected]@@[email protected] = @ILT+15([email protected]@@[email protected]) 
1
以下出口

你需要指定(cpp文件很好)模板专业化。这意味着你需要导出所有模板参数的组合,你要使用:

template __declspec(dllexport) void updateParamValue<int>(const std::string& name, T val); 
template __declspec(dllexport) void updateParamValue<short>(const std::string& name, T val); 
...... 

我在Visual Studio 2013中使用它,它工作。