模板形参要在编译期赋予相应的实参,编译器根据相应的实参构造出相应的函数。
编译期的两步处理
- 语法检查 (比如少没少括号)
- 实例化检查,生成的实例类型是否可以执行模板定义的操作。
会触发编译失败
模板只要求翻译单元级别的一处定义原则,而不是程序级别的一处定义原则。
inline也设置为翻译单元一处定义原则的原因是因为:
要确保它在编译时在所有被调用的地方都可以展开。
万能引用:
实参表达传入右值,那么模板形参被推导为去掉引用的基本类型。
实参如果传入的是左值,模板形参被推导为左值引用,接下来会触发引用折叠。
摘抄来自知乎的关于 顶层const和底层const的讨论,链接
从 const 指针开始说起。
const int* pInt;
和int *const pInt = &someInt;
,前者是 *pInt 不能改变,而后者是 pInt 不能改变。因此指针本身是不是常量和指针所指向的对象是不是常量就是两个互相独立的问题。用顶层表示指针本身是个常量,底层表示指针所指向的对象是个常量。更一般的,顶层 const 可以表示任意的对象是常量,这一点对任何数据类型都适用;底层 const 则与指针和引用等复合类型有关,比较特殊的是,指针类型既可以是顶层 const 也可以是底层 const 或者二者兼备。
显式实例化需要把模板实参的类型都指出来。
缺省的模板实参
函数形参的声明顺序会影响调用的灵活性。
模板和非模板类匹配等级相同(比如都是完美匹配),系统会优先选择非模板类。
显式实例化定义:
显式实例化声明:
目的:避免重复的实例化声明,实例生成,减轻编译器负担。
函数模板特化
针对模板的某种参数组合引入特别的函数版本,显式实例化只需要用声明的形式即可,模板特化需要<> 以及具体的定义。
这个特化本质上也是一种实例。
类的完全特化会引入实例,不完全特化不会引出实例。