模板参数
什么是模板参数
模板参数是在C++中使用模板时,用于指定模板的参数的一种机制。模板参数可以是类型参数、非类型参数或模板参数。
- 类型参数是指在模板中使用的特定类型,可以是内置类型(如int、float等)、自定义的类类型或其他模板类型。
- 非类型参数是指在模板中使用的常量值,可以是整数、字符、枚举或指针。
模板参数可以用于定义模板函数、模板类或模板别名。通过在模板定义中指定参数的类型或值,可以根据实际需求生成特定的函数或类。
例如,以下是一个模板函数的示例,其中T是类型参数,n是非类型参数:
template <typename T, int n>
void printArray(T arr[n]) {
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
}
在使用该模板函数时,需要指定类型参数T和非类型参数n,例如:
int main() {
int arr[] = {1, 2, 3, 4, 5};
printArray<int, 5>(arr);
return 0;
}
在上述示例中,类型参数T被指定为int,非类型参数n被指定为5,从而生成一个可以打印整型数组的函数。
类似函数参数的名字,一个模板参数的名字也没有什么内在含义。
我们通常将类型参数命名为T,但实际上我们可以使用任何名字:
template <typename Foo> Foo calc(const Foo& a, const Foo& b)
{
Foo tmp = a; // tmp的类型与参数和返回类型一样
//...
return tmp: //返回类型和参数类型一样
}
模板参数与作用域
模板参数遵循普通的作用域规则。
一个模板参数名的可用范围是在其声明之后,至模板声明或定义结束之前。
与任何其他名字一样,模板参数会隐藏外层作用域中声明的相同名字。
但是,与大多数其他上下文不同,在模板内不能重用模板参数名:
typedef double A;
template <typename A, typename B> void f (A a, B b)
{
A tmp = a; // tmp的类型为模板参数A的类型,而非double
double B; // 错误:重声明模板参数 B
}
正常的名字隐藏规则决定了A的typedef 被类型参数A 隐藏。因此,tmp不是一个double,其类型是使用f时绑定到类型参数A的类型。
由于我们不能重用模板参数名,声明名字为B的变量是错误的。
由于参数名不能重用,所以一个模板参数名在一个特定模板参数列表中只能出现一次:
//错误:非法重用模板参数名V
template <typename V, typename V> //
模板声明
模板声明必须包含模板参数:
// 声明但不定义 compare和Blob
<typename T>int compare(const T&, const T&);
template <typename T> class Blob;
声明中的模板参数的名字不必与定义中相同:
// 3个calc都指向相同的函数模板
template <typename T>T calc(const T&, const T&);// 声明
template <typename U> U calc(const U&, const U&); //声明
// 模板的定义
template <typename Type>
Type calc(const Type& a, const Type& b) { /*... */}
当然,一个给定模板的每个声明和定义必须有相同数量和种类(即,类型或非类型)的参数。
一个特定文件所需要的所有模板的声明通常一起放置在文件开始位置,出现于Best
任何使用这些模板的代码之前
使用类的类型成员
回忆一下,我们用作用域运算符(::)来访问static成员和类型成员。
在普通(非模板)代码中,编译器掌握类的定义。因此,它知道通过作用域运算