• 文章
  • 顯式模板例項化
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");
}


注意關於連結器錯誤的註釋。解決這個問題的正確方法是模板特化,這樣它會生成一個編譯器錯誤。我只是太懶了,沒做一個例子 >.>. 此外,在實現中使用模板特化的唯一原因是不同型別的行為不同,否則這樣做毫無意義。歡迎透過我的收件箱提出反饋!