• 文章
  • 显式模板实例化
2011年6月26日 (最后更新:2011年6月26日)

显式模板实例化

评分:3.2/5 (196 票)
*****
了解一下

我希望在我的库中有一个模板类,这样我可以轻松地更改支持的字符串数量(遵循类模型)。但是,模板是按需编译的。以下面的例子为例(假设它编译到 libExample.a 中)

头文件 (Example.h)
1
2
3
4
5
template <typename T>
class Example
public:
    Example( T test );
    void setTest( T test );


实现 (Example.cpp)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template <typename T>
class Example
{
public:
    Example( T test )
    {
        _data = test;
    }

    void setTest(T test)
    {
        _data = T;
    }
private:
    T _data;
};


当你将它编译成一个库,并尝试链接来实例化一个带有模板的 "Example" 类时,你会得到一个错误,说明具有模板签名的符号不存在。上面的例子确实可以编译,但它不包含给定的模板实例。

但是,我们可以通过显式模板实例化添加专门的模板支持,这将添加链接库所需的符号(正确)。以下是对 Example.cpp 的修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <typename T>
class Example
{
public:
    Example( T test )
    {
        _data = test;
    }

    void setTest(T test)
    {
        _data = T;
    }
private:
    T _data;
};

class template Example<int>;
class template Example<float>;
class template Example<double>;


现在,只要你只使用允许的类型(int、float、double),头文件仍然有效。只要你链接 libExample.a,以下代码应该可以工作

1
2
3
4
5
6
7
8
9
10
11
#include "Example.h"
#include <string>

int main()
{
    Example<int> example(3);
    Example<float> exampletwo(4.f);
    example.setTest(6);
    //With the given header, the follwing will compile but generate linker errors!
    Example<std::string> example("lol");
}


注意关于链接器错误的注释。解决这个问题的正确方法是模板特化,这样它会生成一个编译器错误。我只是太懒了,没做一个例子 >.>. 此外,在实现中使用模板特化的唯一原因是不同类型的行为不同,否则这样做毫无意义。欢迎通过我的收件箱提出反馈!