名稱空間
變體
操作

類模板

來自 cppreference.com
< cpp‎ | 語言
 
 
C++ 語言
 
 
 
 

類模板定義了一系列類。

目錄

[編輯] 語法

template < 引數列表 > 類宣告 (1)
template < 引數列表 > requires 約束 類宣告 (2) (C++20 起)
export template < 引數列表 > 類宣告 (3) (在 C++11 中已移除)

[編輯] 解釋

類宣告 - 一個類宣告。宣告的類名成為模板名。
引數列表 - 一個非空的逗號分隔的模板引數列表,每個引數都是非型別引數型別引數模板引數或這些引數的引數包
約束 - 一個約束表示式,它限制此類模板接受的模板引數。
export 是一個可選修飾符,用於將模板宣告為已匯出(與類模板一起使用時,它也將其所有成員宣告為已匯出)。例項化匯出模板的檔案不需要包含其定義:宣告就足夠了。export 的實現很少見,並且在細節上彼此不一致。 (C++11 前)

[編輯] 類模板例項化

類模板本身不是型別、物件或任何其他實體。僅包含模板定義的原始檔不會生成任何程式碼。為了使任何程式碼出現,必須例項化模板:必須提供模板引數,以便編譯器可以生成實際的類(或函式,來自函式模板)。

[編輯] 顯式例項化

template 類鍵 模板名 < 引數列表 > ; (1)
extern template 類鍵 模板名 < 引數列表 > ; (2) (C++11 起)
類鍵 - class, structunion
1) 顯式例項化定義
2) 顯式例項化宣告

顯式例項化定義強制例項化它們所引用的類、結構體或聯合體。它可以在模板定義之後的程式中的任何位置出現,對於給定的引數列表,在整個程式中只允許出現一次,不需要診斷。

顯式例項化宣告 (extern template) 跳過隱式例項化步驟:否則會導致隱式例項化的程式碼會使用其他地方提供的顯式例項化定義(如果不存在此類例項化,則會導致連結錯誤)。這可以用於透過在所有使用它的原始檔(除一個檔案外)中顯式宣告模板例項化,並在剩餘檔案中顯式定義它來減少編譯時間。

(C++11 起)

類、函式、變數(C++14 起)和成員模板特化可以從它們的模板顯式例項化。類模板的成員函式、成員類和靜態資料成員可以從它們的成員定義顯式例項化。

顯式例項化只能出現在模板的包圍名稱空間中,除非它使用限定 ID

namespace N
{
    template<class T>
    class Y // template definition
    {
        void mf() {}
    };
}
 
// template class Y<int>; // error: class template Y not visible in the global namespace
using N::Y;
// template class Y<int>; // error: explicit instantiation outside
                          // of the namespace of the template
template class N::Y<char*>;       // OK: explicit instantiation
template void N::Y<double>::mf(); // OK: explicit instantiation

如果對於同一組模板引數,之前已經出現了顯式特化,則顯式例項化無效。

當顯式例項化函式模板、變數模板(C++14 起)、類模板的成員函式或靜態資料成員,或成員函式模板時,只需要宣告可見。類模板、類模板的成員類或成員類模板的完整定義必須出現在顯式例項化之前,除非之前出現了具有相同模板引數的顯式特化。

如果函式模板、變數模板(C++14 起)、成員函式模板或類模板的成員函式或靜態資料成員透過顯式例項化定義進行顯式例項化,則模板定義必須存在於同一翻譯單元中。

當顯式例項化命名類模板特化時,它作為其每個尚未在翻譯單元中顯式特化的非繼承非模板成員的相同種類(宣告或定義)的顯式例項化。如果此顯式例項化是一個定義,它也僅是此時已定義的成員的顯式例項化定義。

顯式例項化定義忽略成員訪問說明符:引數型別和返回型別可以是私有的。

[編輯] 隱式例項化

當代碼在需要完全定義型別的上下文中引用模板,或者當型別的完整性影響程式碼時,並且此特定型別尚未顯式例項化時,會發生隱式例項化。例如,當此型別的物件被構造時,但當此型別的指標被構造時則不會。

這適用於類模板的成員:除非在程式中使用該成員,否則它不會被例項化,也不需要定義。

template<class T>
struct Z // template definition
{
    void f() {}
    void g(); // never defined
};
 
template struct Z<double>; // explicit instantiation of Z<double>
Z<int> a;                  // implicit instantiation of Z<int>
Z<char>* p;                // nothing is instantiated here
 
p->f(); // implicit instantiation of Z<char> and Z<char>::f() occurs here.
        // Z<char>::g() is never needed and never instantiated:
        // it does not have to be defined

如果在例項化點聲明瞭類模板但未定義,則例項化會產生不完整的類型別

template<class T>
class X;    // declaration, not definition
 
X<char> ch; // error: incomplete type X<char>
區域性類以及其成員中使用的任何模板,都作為宣告區域性類或列舉的實體例項化的一部分而例項化。 (C++17 起)

[編輯] 關鍵詞

export(直到 C++11)extern(C++11 起)

[編輯] 另見