2009-12-28 67 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中使用它,它工作。