1.无类型模板参数
- 由于N的值在编译时时已知的,内含的data数组可以被置于运行时堆栈,而不是动态存储空间。
- 任意一个N的取值都会产生一个惟一的类类型。
template<class T, size_t N> class Stack {
T data[N];
size_t count;
public:
void push(const T&t);
};
2.默认模板参数
- 可以为模板的所有参数提供默认值,但当声明一个实例时必须使用一对空的尖括号,这样编译器就知道说明了一个类模板。
eg: Stack<> mystack;
- 注意: 在最后两个尖括号字符之间有空格,这就避免了编译器将两个字符(> > )解释为右移运算符。
template<class T, class Allocator = allocator<T> >
class vector;
3.模板类型的模板参数
- 此处使用了默认值,这也是与前面所陈述的规则——即默认参数在一个编辑单元内仅能出现一次——惟一的例外。
Template<class T, size_t N = 10>
class Array {
...
};
template<class T, template<class, size_t=10> class Sq>
class Container {
...
}
4.typename关键字
- 如果没有typename,编译器会把T::id当作对象而不是嵌套类型。不能认为关键字typename关键字创建了一个新类型名,它的目的只是通知编译器,被限定的那个标识符应该被解释为一个类型。
template<class T> class X {
typedef T::id i;
public:
void f() {
i.g(); }
};
class Y {
public:
class id{
public:
void g() {
}
};
};
int main(int argc, char const *argv[])
{
X<Y> xy;
xy.f();
return 0;
}
- 关键字typename的另一个作用是,可以在模板定义的模板参数列表中选择使用typename代替class:
template<typename T> class X {
int main() {
X<int> x;
}
};
5.函数模板重载
- 可以用相同的函数名重载函数模板,编译器在处理程序中的函数调用时,必须能够知道哪一个模板或普通函数是最适合调用的函数
#include <cstring>
#include <iostream>
using std::strcmp;
using std::cout;
using std::endl;
template<typename T> const T& min (const T& a, const T& b) {
return (a < b) ? a : b;
}
const char* min(const char* a, const char* b) {
return (strcmp(a, b) < 0) ? a : b;
}
double min(double x , double y) {
return (x < y) ? x : y;
}
int main(int argc, char const *argv[])
{
const char* s2 = "say hello", *s1 = "knights whowhowho";
cout << min(1, 2) << endl;
cout << min(1.0, 2.0) << endl;
cout << min(1, 2.0) << endl;
cout << min(s1, s2) << endl;
cout << min<> (1, 2) << endl;
return 0;
}
- 之所以在应该用using namespace std;处用几个using声明,是因为有些编译器在其中包含了std::min()的头文件,这将导致冲突