C++泛型設計 - 模板規格(譯)
C++關鍵字template可以用來聲明一批參數化的類(模板類)或函數(模板函數)。
一般使用格式如下:
template < template-parameter-list > declaration
說明
template-parameter-list是一個以逗號分隔開的模板參數。這些模板參數可能是一些類型(以這種格式:class identifier,typename identifier或是template<template-parameter-list> class identifier)或是一些非類型的參數,它們常用於模板體內,代表着實際使用時指定的類型或是非類型的對象。模板參數的語法如下之一:
parameter-declaration
² class identifier [ = typename ]
² typename identifier [ = typename ]
² template < template-parameter-list > class [identifier][= name]
你可以像實例化一個普通類一樣去實例化一個類模板多次,但你必須以一對尖括號(<>)來包含模板參數。這些模板參數可以是任意類型(template-parameter-list包含class或是typename關鍵字)或是一個適當類型的值(template-parameter-list包含非類型的參數)。調用一個模板函數沒有特定的語法,儘管尖括號和模板參數是必需的(當模板參數不能由參數到函數引出時)。
如下所示,template-parameter-list的幾個部分都是不同的,這些參數主要用於在模板類中的函數。
template< class T, int i > class MyStack...
在這個例子中,這個模板可以接愛一個類型(class T)和一個常量參數(int i)。上面這個例子的模板將使用類型T和常量的整數i。在MyStack聲明的類體中,你必須引用到這個標識符T。
一個模板的聲明不會產生代碼,它僅闡釋一個類或函數的組織,當它被其它代碼引用時纔會產生。
模板可以在全局或是名字空間及類域下進行聲明,但不能在一個函數內聲明。
下面這個例子演示了一個類模板以一個類型T及一個非類型模板參數i進行的聲明、定義及實例化:
實例
////////////////////////////////////////////////////////////////////////////////////////////////
// template_specifications1.cpp
// Template Class Usage 1: The T is Type, and the i is constant value of Integer
template <class T, int i>
class TestClass
{
public:
char buffer[i];
T testFunc( T* p1 );
};
template <class T, int i>
T TestClass<T, i>::testFunc(T* p1)
{
return *(p1++);
}
// To create an instance of TestClass
TestClass<char, 5> ClassInst;
int main()
{}
////////////////////////////////////////////////////////////////////////////////////////////////
// template_specifications2.cpp
class Y
{};
// Template Class Usage 2: The pT is Value of Pointer
template <class T, T* pT>
class X1
{};
// Template Class Usage 3: The T2 is optional Default Parameter
template <class T1, class T2 = T1>
class X2
{};
// To create those instances of upon classes
Y aY;
X1<Y, &aY> x1;
X2<int> x2;
int main()
{}
////////////////////////////////////////////////////////////////////////////////////////////////
// template_specifications3.cpp
#include <stdio.h>
// Template Structure Usage 1:Normal
template <class T>
struct str1
{
T t;
};
// Template Structure Usage 2:The Type of T can be a template class
template <template<class A> class T>
struct str2
{
T<int> t;
};
int main()
{
str2<str1> mystr2;
mystr2.t.t = 5;
printf_s( “%d/n”, mystr2.t.t );
}
/* ---------------------- */
輸出
5
////////////////////////////////////////////////////////////////////////////////////////////////
// references__supported_as_nontype_template_parameters.cpp
#include <stdio.h>
extern “C” int printf( const char*, ... );
template <int& ri>
struct S
{
// constructor method
S()
{
printf( “ ri is %d/n”, ri );
}
// destructor method
~S()
{
printf( “ri is %d/n”, ri );
}
};
int i = 1;
int main()
{
S<i> s;
i = 0;
}
/* ---------------------- */
輸出
ri is 1
ri is 0
////////////////////////////////////////////////////////////////////////////////////////////////
非類型的模板參數
非類型的模板參數必須是:整數/枚舉/指針/引用/指向一個成員類型的指針(例如template_specifications2.cpp的X1模板類)。正如const或volatile類型一樣,在編譯時刻它們是不可改變的。另外,float類型的指針不能用作模板參數。儘管一個指向 “類對象/結構/union類型”的指針可用作模板參數,但是它們本身卻不可用作模板參數。若傳遞的是數組名稱,就被轉化爲指針看待。若傳遞的是函數名稱,當然,是被看作爲函數指針。字符串是不允許看作爲模板參數的。
在一個模板聲明中使用typename
在模板參數列表中,可以使用typename關鍵字來定義一個參數。例如下面的模板聲明是一樣的:
template <class T1, class T2> class X...
template <typename T1, typename T2> class X...
缺省的模板參數
類模板可以擁有缺省參數(指定使用賦值操作符賦一個缺省的類型或是一個值)。確記,函數模板不可有缺省參數。
////////////////////////////////////////////////////////////////////////////////////////////////
/* 類模板缺省參數用法參考簡單例子 */
template<typename Type>
class allocator
{};
template<typename Type, typename Allocator = allocator<Type>>
class stack
{};
stack<int> MyStack;
////////////////////////////////////////////////////////////////////////////////////////////////
模板參數的複用
在模板參數列表中,模板參數可以複用。如template_specifications2.cpp例子中的X1模板類的模板參數T在第二個參數中獲得到複用。
模板的模板參數
模板參數也可以進行模板化。這個創立前提條件是,參數本身必須是一個模板,非一個由模板構造好的類。在下面的例子中,模板參數的名稱A對於一個模板的模板參數來說,可以省略,因爲沒有被使用。
引用模板參數
Visual Studio .NET 2003引入了一個新特性,可以引用非類型的模板參數。這個方法在以前的版本中是不允許的。
—完—