【C++】模板与泛型编程(一):定义模板,模板参数
16.1.3 模板参数
类似函数参数的名字,一个模板参数的名字也没有什么内在含义。通常将类型参数命名为 T,但实际上可以使用任何名字。(本节内容与template <typename T>
当中的 T 有关)
模板参数与作用域
模板参数遵循普通作用域规则。一个模板参数名的可用范围是在其声明之后,至模板声明或定义结束之前。与任何其它名字一样,模板参数会隐藏外层作用域中声明的相同名字。但是与绝大多数其它上下文不同,在模板内不能重用模板参数名。
模板声明
模板声明必须包含模板参数:
template<typename T> int compare(const T&, const T&);
template<typename T> class Blob;
最佳实践:一个特定文件所需要的所有模板声明通常一起放置在文件开始位置,出现于任何使用这些模板的代码之前。
使用类的类型成员
默认情况下,C++ 假定通过作用域运算符访问的名字不是类型。因此如果我们希望使用一个模板类型参数的类型成员,就必须显式告诉编译器该名字是一个类型,使用 typename 来实现这一点:
template <typename T>
typename T::value_type top(const T& c) {
// ... ... ...
}
默认模板实参
就像我们可以为函数参数提供默认实参一样,我们也可以提供默认模板实参。
现在我们重写 compare,默认使用标准库中的 less 函数对象模板:
template<typename T, typename F = less<T>>
int compare(const T &v1, const T &v, F f = F()) {
if(f(v1, v2)) return -1;
if(f(v2, v1)) return 1;
return 0;
}
模板默认实参与类模板
无论何时使用一个类模板,都必须显式地在模板名之前加上尖括号。尖括号指出类必须从一个模板实例化而来:
template <class T = int> class Numbers {
public:
Numbers(T v = 0): val(v) { }
// ... ... ...
private:
T val;
};
Numbers<long double> lots_of_precision;
Number<> average_precision; // 空的 <> 表明我们希望使用默认类型