c++模板與泛型編程基礎

泛型編程就是以獨立於任何特定類型的方式編寫代碼,而模板是泛型編程的基礎。

(1)定義函數模板(function template)

函數模板是一個獨立於類型的函數,可以產生函數的特定類型版本。

// implement strcmp-like generic compare function
template <typename T>
int compare(const T &v1, const T &v2)
{
    if (v1 < v2) return -1;
    if (v2 < v1) return 1;
    return 0;
}

模板定義以關鍵字template開始,後接尖括號括住的模板形參表。

模板形參可以是表示類型的類型形參(type parameter),也可以是表示常量表達式的非類型形參(nontype parameter)。上面程序中的T是類型形參。

// compiler instantiates int compare(const int&, const int&)
cout << compare(1, 0) << endl;
// compiler instantiates int compare(const string&, const string&)
string s1 = “hi”, s2 = “world”;
cout << compare(s1, s2) << endl;

使用函數模板時,編譯器會將模板實參綁定到模板形參。編譯器將確定用什麼類型代替每個類型形參,用什麼值代替每個非類型形參,然後產生並編譯(稱爲實例化)該版本的函數。

上面的例子中,編譯器用int代替T創建第一個版本,用string代替T創建第二個版本。

函數模板也可以聲明爲inline。

// inline specifier follows template parameter list
template <typename T> inline T min(const T&, const T&);

(2)定義類模板(class template)

在定義的類模板中,使用模板形參作爲類型或值的佔位符,在使用類時再提供具體的類型或值。

template <typename Type> 
class Queue
{
public:
    Queue();
    Type & front();
    const Type & front() const;
    void push(const Type &);
    void pop();
    bool empty() const;
private:
    // …
};
與調用函數模板不同,使用類模板時,必須爲模板形參顯示指定實參。
Queue<int> qi; // Queue that holds ints
Queue<string> qs; // Queue that holds strings

(3)模板類型形參

類型形參由關鍵字class或typename後接說明符構成。在函數模板形參表中,二者含義相同。typename其實比class更直觀,更清楚的指明後面的名字是一個類型名(包括內置類型),而class很容易讓人聯想到類聲明或類定義。

此外,在使用嵌套依賴類型(nested depended name)時,必須用到typename關鍵字。

在類的內部可以定義類型成員。如果要在函數模板內部使用這樣的類型,必須顯示告訴編譯器這個名字是一個類型,否則編譯器無法得知它是一個類型還是一個值。默認情況下,編譯器假定這樣的名字指定(靜態)數據成員,而不是類型。所以下面這段程序,如果去掉typename關鍵字,將會出現編譯錯誤。

template <typename Parm, typename U>
Parm fcn(Parm *array, U value)
{
    typename Parm::size_type * p;
}

(4)非類型模板形參

模板形參也可以是非類型形參,在使用時非類型形參由常量表達式代替。

// initialize elements of an array to zero
template <typename T, size_t N>
void array_init(T (&parm)[N])
{
    for (size_t i = 0; i != N; ++i)
        parm[i] = 0;
}
…
int x[42];
double y[10];
array_init(x); // instantiates array_init(int (&)[42])
array_init(y); // instantiates array_init(double (&)[10])

(5)編寫泛型程序

模板代碼需要對使用的類型做一些假設,比如上面的compare()要求類型T重載了“<”操作符。所以函數模板內部完成的操作就限制了可用於實例化該函數的類型。

編寫模板代碼時,對實參類型的要求應儘可能少。比如compare()函數僅使用了“<”操作符,而沒有使用“>”操作符。

【學習資料】 《c++ primer》






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章