在摸板定义中,模板参数列表不能为空,
编译器用推断出的参数来进行 实例化(instantiation)
一般来说 模板是有type parameter
但是也可以声明 nontype parameter
template<unsgned N,unsigned M>
int compare(const char(&p) [n], const char(&p2)[M]){
return strcmp(p1,p2);
}
compare("hi","mom")
在执行时 ,实际上 实例化(instantiaton) 出的是 int compare(const char (&p)[3] ...
因为编译器会在字符串常量的末尾添加一个空字符作为终结符
- 一个非类型参数(nontype patameter) 可以是一个整形,或者是一个指向对象或函数类型的 指针 或者 (左值)引用
- 绑定到 非类型整形参数的实参 必须是一个常量表达式
- 绑定 指针或引用 的非类型参数 实参必须具有静态的生存期
- 不能使用一个普通(非 static ) 的局部变量或动态对象 作为 指针或引用 非类型模板参数的实参。
- 指针参数可以使用nullptr 或者 一个值为0 的常量表达式 来进行 实例化
+模板定义内 nontype parameter 是一个常值量 ,可以使用在需要长治表达式的地方 比如指定数组 的大小
可以声明为 inline 或者 constexpr 在模板参数列表之后 返回类型之前
编写泛型代码的两个重要原则
- 模板中函数参数是const 引用
- 函数体的判断中仅仅使用了 < 比较操作
通过将函数参数设置为const 的引用 ,我们就保证了函数可以用于不能拷贝的对象上面
调用函数的时候 编译器需要掌握函数的声明,
所以函数声明和类定义都放在头文件里面。而函数的方法体与类的成员函数可以放在源文件中
模板则不同,为了生成一个实例化版本,编译器需要掌握函数模板或类模板成员函数的定义,因此 模板的头文件 通常既包括声明也包括定义
模板大多到实例化期间才会 有编译错误
这主要在三个阶段报告错误
- 编译模板本身时,这一阶段检查语法错误
- 遇到模板使用时,检查参数匹配是否正确
- 模板实例化时 ,这一阶段发现类型相关的错误,可能在连接的时候才报告
编译器不能为类模板 推断模板参数类型 必须在模板名后的尖括号提供额外的信息---- 用来代替模板参数的模板实参列表
下面是一个列子
template <typename T> class Blob{
public:
typedef T value_type;
typedef_ typename std::vector<T>::size_type size_type; //这里 是说编译器在实例化之前 是不知道 vector<T>::size_type 是什么东西