template <class T>
template <class T, class U>
template <class T, int N>
template <class T = char>
template <int Tfunc (int)>
從編譯器的角度來看,模板不同于一般的函數或類。
它們在需要時才被編譯(compiled on demand),
也就是說一個模板的代碼直到需要生成一個對象的時候(instantiation)才被編譯。
當需要instantiation的時候,編譯器根據模板為特定的調用數據類型生成一個特殊的函數。
當工程變得越來越大的時候,程序代碼通常會被分割為多個源程序文件。
在這種情況下,通常接口(interface)和實現(implementation)是分開的。
用一個函數庫做例子
接口通常包括所有能被調用的函數的原型定義。
它們通常被定義在以.h 為擴展名的頭文件 (header file) 中;
而實現 (函數的定義)
則在獨立的C++代碼文件中。
模板這種類似宏(macro-like) 的功能,對多文件工程有一定的限制:
函數或類模板的實現 (定義) 必須與原型聲明在同一個文件中。
也就是說我們不能再 將接口(interface)存儲在單獨的頭文件中,
而必須將接口和實現放在使用模板的同一個文件中。
回到函數庫的例子,如果我們想要建立一個函數模板的庫,我們不能再使用頭文件(.h) ,取而代之,我們應該生成一個模板文件(template file),將函數模板的接口和實現 都放在這個文件中 (這種文件沒有慣用擴展名,除了不要使用.h擴展名或不要不加任何擴展名)。
在一個工程中多次包含同時具有聲明和實現的模板文件并不會產生鏈接錯誤 (linkage errors),因為它們只有在需要時才被編譯,而兼容模板的編譯器應該已經考慮到這種情況,不會生成重復的代碼。