2013-02-26 99 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