//模板参数和作用域
//模板参数遵循普通的作用域规则,模板参数会隐藏外层作用域声明的相同名字,
//但是在模板内不能重用模板参数名。
typedef double A;
template<typename A, typename B>
void f(A a, B a)
{
A tem = a;//tmp的类型为模板参数A的类型,而非double
double B;//错误 重声明模板参数B
}
//因为模板参数名不能重用,所以一个模板参数名在一个模板参数列表中只能出现一次
//template<typename A, typename A>//错误 出现了两次A
//模板声明
//模板声明必须包含模板参数
template <typename T> int compare(const T&, const T&);
template <typename T> class Blob;
//声明中的模板参数的名字不必与定义相同,有相同数量和种类的参数就是同一个模板
//下边三个是同一个函数模板
template <typename T> calc(const T&, const T&);//声明
template <typename U> calc(const U&, const U&);//声明
template <typename Type> calc(const Type&, const Type&){/* ... */}//定义
//使用类的类型成员
//可以使用typename显示的告诉编译器该名字是一个类型,不能使用class
template<typename T>
typename T::value_type top(const T& c)
{
if (!c.empty())
return c.back();
else
return typename T::value_type();//生成一个值初始化的元素
}
//默认模板实参
template <typename T, typename F = less<T>>
int compare(const T &v1, const T& v2, F f = F())
{
if (f(v1, v2)) return -1;
if (f(v2, v1)) return 1;
return 0;
}
bool i = compare(1, 2);
//模板默认实参与类模板
template<class T = int>//T默认为int
class Numbers {
public:
Numbers(T v = 0) :val(v) {}
private:
T val;
};
//如果使用类模板的默认实参,就必须在模板名之后跟一个空尖括号对
Numbers<long double> lots_of_precision;//没有使用默认类型
Numbers<> average_precision;//使用<>表示使用默认类型