命名空間
變體
動作

類別模板

出自 cppreference.com
< cpp‎ | language
 
 
C++ 語言
一般主題
流程控制
條件執行陳述式
if
疊代陳述式 (迴圈)
for
範圍 for (C++11)
跳躍陳述式
函式
函式宣告
Lambda 函式運算式
inline 指定符
動態例外規範 (直到 C++17*)
noexcept 指定符 (C++11)
例外
命名空間
型別
指定符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
儲存期指定符
初始化
 
 
 
 

類別樣板定義了一組類別。

目錄

[編輯] 語法

template < 參數列表 > 類別宣告 (1)
template < 參數列表 > requires 約束 類別宣告 (2) (自 C++20 起)
export template < 參數列表 > 類別宣告 (3) (於 C++11 移除)

[編輯] 說明

類別宣告 - 一個 類別宣告。所宣告的類別名稱成為樣板名稱。
參數列表 - 一個非空的逗號分隔列表,包含 樣板參數,每一個參數可以是 非型別參數型別參數樣板樣板參數,或是上述任何一種的 參數包
約束 - 一個 約束表達式,用於限制此類別樣板可接受的樣板參數
export 曾是一個選擇性的修飾符,用於將樣板宣告為「已匯出」(當用於類別樣板時,它也會將其所有成員宣告為已匯出)。實例化已匯出樣板的檔案不需要包含其定義:宣告即已足夠。export 的實作極為罕見,且各編譯器對於細節的定義亦不一致。 (直到 C++11)

[編輯] 類別樣板實例化

類別樣板本身並非型別、物件或任何其他實體。僅包含樣板定義的原始程式檔不會產生任何程式碼。為了使程式碼出現,樣板必須經過實例化:必須提供樣板引數,以便編譯器能夠產生一個實際的類別(若為函式樣板,則產生函式)。

[編輯] 顯式實例化

template 類別鍵 樣板名稱 < 引數列表 > ; (1)
extern template 類別鍵 樣板名稱 < 引數列表 > ; (2) (C++11 起)
類別鍵 - classstructunion
1) 顯式實例化定義
2) 顯式實例化宣告

顯式實例化定義會強制其實例化所指的類別、結構或聯合。它可以在程式中樣板定義後的任何位置出現,且對於給定的 引數列表,在整個程式中只允許出現一次,不需要診斷訊息。

顯式實例化宣告(extern 樣板)會跳過隱式實例化步驟:原本會導致隱式實例化的程式碼,改為使用在其他地方提供的顯式實例化定義(若不存在此類實例化,將導致連結錯誤)。這可用於減少編譯時間,方法是在除一個原始程式檔之外的所有使用該樣板的檔案中宣告顯式實例化,並在剩餘的檔案中進行定義。

(C++11 起)

類別、函式、變數(C++14 起)以及成員樣板特化可以從其樣板中進行顯式實例化。類別樣板的成員函式、成員類別和靜態資料成員可以從其成員定義中進行顯式實例化。

顯式實例化只能出現在樣板的封閉命名空間中,除非使用限定識別碼 (qualified-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 起)、成員函式樣板,或類別樣板的成員函式或靜態資料成員,透過顯式實例化定義進行顯式實例化,則樣板定義必須存在於同一個轉譯單元中。

當顯式實例化命名一個類別樣板特化時,它會作為該特化之每個「非繼承的非樣板成員」(且尚未在該轉譯單元中被顯式特化)的相同類型(宣告或定義)之顯式實例化。若此顯式實例化是一個定義,則它僅對該時間點已定義的成員而言,才屬於顯式實例化定義。

顯式實例化定義會忽略成員存取說明符:參數型別和回傳型別可以是私有的 (private)。

[編輯] 隱式實例化

當程式碼在需要完整定義型別的語境下參考樣板,或者當型別的完整性影響程式碼,且該特定型別尚未被顯式實例化時,就會發生隱式實例化。例如,建構該型別的物件時會發生,但建構指向該型別的指標時則不會。

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

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 起)

[編輯] 參見

English Deutsch 日本語 한국어 中文(简体) 中文(繁體)