2013-02-26 103 views
7

我正在研究一個靜態庫,並且該庫有多個類模板和函數模板。我明白爲了使用靜態庫內的模板,所有的東西(聲明/定義)都需要在頭文件中。然而,在這種特殊的情況下,因爲我知道我認爲我可以用forward的專業化類型來代替專業化。具有模板實例化的模板靜態庫

這個技巧與類模板(及其功能)很好地結合,我可以使用我的應用程序代碼中的所有庫函數。然而,當我介紹免費函數模板庫中,我嘗試使用免費的模板功能從我的應用程序代碼,它給了我鏈接錯誤:

error LNK2019: unresolved external symbol "class TemplatedStaticLib __cdecl HelpingRegistration(int)" ([email protected]@@[email protected]@@[email protected]) referenced in function _main 1>C:\src\cpp\vs2008\StaticLibExample\MathFuncsLib\Debug\TemplatedStaticLibApp.exe : fatal error LNK1120: 1 unresolved externals" I am using VS2008, here is the code

//靜態庫的頭文件(.h)中

#ifndef _TEMPLATED_STATIC_LIB_ 
#define _TEMPLATED_STATIC_LIB_ 

#include <iostream> 

template<typename T> 
class TemplatedStaticLib 
{ 
public: 
    TemplatedStaticLib(){}; 
    ~TemplatedStaticLib(){}; 

    void print(T t); 

}; 

template<typename T> 
TemplatedStaticLib<T> HelpingRegistration(T); 


#endif 

//靜態庫類文件(的.cpp)

#include "TemplatedStaticLib.h" 

//Specialization 
template class TemplatedStaticLib<double>; 
template class TemplatedStaticLib<int>; 
template class TemplatedStaticLib<std::string>; 


template<typename T> 
void TemplatedStaticLib<T>::print(T t) 
{ 
    std::cout << "Templated Print " << typeid(t).name() << std::endl; 
} 

void HelpingRegistration(void) 
{ 
} 

//Specialization of free function 
template<> TemplatedStaticLib<int> HelpingRegistration<int>(int); 
template<> TemplatedStaticLib<double> HelpingRegistration<double>(double); 
template<> TemplatedStaticLib<std::string> HelpingRegistration<std::string>(std::string); 

template<typename T> 
TemplatedStaticLib<T> HelpingRegistration(T t) 
{ 
     std::cout << "Function Templated Print " << typeid(t).name() << std::endl; 
     return t; 
} 

//應用程序代碼

#include "TemplatedStaticLib.h" 

int main(int argc, char* argv[]) 
{ 
    int anInt = 99; 
    TemplatedStaticLib<int> test; 
    test.print(anInt);//works 

    double aDouble = 3.9; 
    TemplatedStaticLib<double> double_test; 
    double_test.print(aDouble); //works 

    std::string aString = "James"; 

    TemplatedStaticLib<std::string> string_test; 
    string_test.print(aString);//works 

    //The following lines gives linker error 
    HelpingRegistration(anInt); 
    HelpingRegistration(aDouble); 
    HelpingRegistration(aString); 


    return 0; 
} 

我不知道爲什麼它是不同的,我如何解決這個問題。任何幫助表示讚賞。

+1

無法在翻譯單元中定義模板。 – 0x499602D2 2013-02-26 01:12:47

+0

模板濫用的經典示例 – 2013-02-26 01:20:01

+0

嗯,我想知道爲什麼它適用於類模板的情況呢? – jazaman 2013-02-26 01:24:35

回答

8

請注意,這些是而不是轉發聲明,而是您的類模板的顯式實例。這就是允許您將定義放在.cpp文件中,並且鏈接器不會獲得未解決的引用錯誤,只要在其他翻譯單元中只使用這些模板實例。

在另一方面,這些:

template<> TemplatedStaticLib<int> HelpingRegistration<int>(int); 
template<> TemplatedStaticLib<double> HelpingRegistration<double>(double); 
template<> TemplatedStaticLib<std::string> HelpingRegistration<std::string>(std::string); 

明確專業化的函數模板聲明。您最可能打算做的是提供顯式實例。對於這樣做的語法如下:

template TemplatedStaticLib<int> HelpingRegistration<>(int); 
template TemplatedStaticLib<double> HelpingRegistration<>(double); 
template TemplatedStaticLib<std::string> HelpingRegistration<>(std::string); 

一旦你解決這個問題,你會看到,編譯器將實際實例化HelpingRegistration<>()函數模板,並且它也將這樣做時,發出一個錯誤,因爲你正試圖轉換一個int到類型TemplatedStaticLib<int>(相應TemplatedStaticLib<double>TemplatedStaticLib<string>。)的目的,對於沒有轉換設置(或至少未示出在您發佈的代碼)(相應一個doublestring):

template<typename T> 
TemplatedStaticLib<T> HelpingRegistration(T t) 
{ 
    std::cout << "Function Templated Print " << typeid(t).name() << std::endl; 
    return t; // CANNOT BE CONVERTED! 
} 

修復此錯誤(例如,通過做return TemplateStaticLib<T>();)將使程序編譯鏈接。

+0

非常感謝@Andy的線索,我所需要的只是功能模板的顯式實例化,而不是顯式專業化,謝謝指出轉換問題。其實根本不需要轉換。所以我修改了專門化模板<> TemplatedStaticLib HelpingRegistration (int)to template void HelpingRegistration (int t),所有的作品都像魅力一樣。 – jazaman 2013-02-26 02:03:43

+0

@jazaman:好的,很高興我能幫忙:-) – 2013-02-26 02:05:50