函数模版:
1 模版函数使用时,是不允许自动类型转换的,通过实参演绎,生成对应函数实例。
2,模版实参演绎不是和模版函数的返回类型, 可以通过交换模版参数位置,实现返回类型的显示实例化。
3 函数模版实例通常被看成用来命名一组重载函数的集合,所以用函数模版实例 去演绎 函数模版参数时,需要指定该函数模版实例的具体类型。(C++ templates P37,这句话看了好几天)
4 使用字符串引用参数的函数模版,C字符串长度不同,会实例化为不同的函数模版实例。由于字符串是char const[]类型,如果模版参数是非引用参数,实参数组会退化成指针类型。
5 对于短小的模版函数,如果是声明为内联,必须加上inline修饰符。
类模版:
1 成员函数只有在被使用时才会实例化。
2 如果类模版中含有静态成员,那么实例化的每种类型,都会实例化这些静态成员。
3 类模版有全特化和偏特化。
4 模版的模版参数为类模版时,必须用class 来标志参数,指明其为模版类。
5 虚成员函数不能定义为成员函数模版。
6 只有类模版声明才能具有缺省模版实参。
8 类模版特化的成员实现,不可以写template<>。
9 对于那些在基类中声明,并且依赖于模版参数的符号,应该前面使用this或者Base<T>::。
10 对于已经显示实例化过的成员,就不能在此对这些成员显示实例化。
模版参数类型
1 非类型的模版参数只能是常数(包括枚举值),或者外面链接对象的指针以及引用。浮点书和类对象是不允许为非类型模版参数。
2 使用字符串作为函数模版实参,不要将函数参数声明为引用。
3 对于非引用类型的参数,在实参演绎过程中,会出现数组到指针的退化,
模版组织等问题
1 显示实例化语法 http://docs.oracle.com/cd/E19205-01/820-1214/bkafi/index.html。
2 两种包含模型方法 http://www.cnblogs.com/lvdongjie/p/4288373.html
3 包含头文件应该使尽量多的头文件顺序一致,将版本比较稳定的头文件放在前面。
4 类模版显示实例化预留位置
5 类模版偏特化预留位置
公共问题
1 缺省调用实参可以依赖于模版参数。
3 局部类,局部枚举和未命名的class和枚举不能作为模版的类型实参。
4 缺省的函数参数,缺省的模版参数,缺省参数的后面参数必须都缺省。
5 模版的名字不具备C链接(待理解)
6 ADL 只能应用于非受限名称
7 遇到POI位置时,编译器必须看到相应模版的定义。
8 编译长度为零的数组,编译器没有报错,和C++ templats P141有点冲突,负数确实报错了。
9 编译时期,若函数模版和成员模版函数为实例化,编译器对模版函数以及成员模版函数只做参数和返回类型检查,函数里面不做检查。
友元类
1 友元类的声明不能是类定义,可以命名一个特定的类模版实例为友元
2 友元类为类模版实例时,该模版的声明必须可见,普通类怎不必要
友元函数
1 不能在友元声明中定义一个模版实例,由于友元类不能是定义,故不会出现此类问题。普通友元函数可以出现定义,命名一个实例的友元声明是不能作为定义。看C++templates P111
2 在类定义中,受限的友元不能是函数的定义
3 如果名称不受限,那么该名称一定不是引用一个模版实例(待理解)
4 在类模板内部定义友元函数,友元函数的参数类型或返回类型必须包含类模板的模板参数。否则该友元函数会被定义两次。
POI位置(包含了实例化位置的解释):
非类型显示实例化的引用(C++templates用特化,感觉有点不对,不是吹毛求疵,里面的概念太多,稍微混肴可能理解不对):包含这个引用的定义或声明之后的最近名字空间域。
类实例的引用:包含这个实例引用的定义或声明之前的最近名字空间域
实例化中又有实例化:实例化点外和内分别设为POI1,POI2, POI1还是遵循上面规则。
POI2位置: 1 对于显示实例化引用的,即非依赖型的引用,遵循上面的规则,放在引用处的上面或下面。
2 对于依赖型引用的,遵循上面的规则,放在POI1的上面或下面。
3 真正实例化位置选择: 一个翻译单元如果包含多个POI:
类模板:在每个翻译单元中,只有首个POI保留。
对于非类型实例:所有POI都会保留,但编译器会选择一个POI位置进行实例化(ODR原则要求所有的POI的实例化体都等价,这种等价性编译器没有保证也没有检查。实际应用中大多数编译器会延迟非内联函数模版的实例化,知道翻译单元末尾 处,进行实例化。)
延迟实例化(讲了实例化程度):
隐式实例化类模版:实例化该模版的每个成员声明,不实例化相应的定义(除类模版中包含匿名union,虚函数的定义不一定实例化)
实例化函数或者成员函数:在被调用处实例化。(如果在函数调用过程中,确实用到了缺省实参,该实参也会被实例化。好像不对)
两阶段查找
第一阶段:即编译器第一次看到模版的时候、 编译器会使用普通查找规则和ADL规则查找 非依赖型名称。 用普通规则查找 依赖型受限函数名称(函数参数是依赖型),保存查找结果,并不会试图进行重载解析。
第二阶段:在POI位置。 会使用普通查找规则和ADL规则查找依赖型受限名称。依赖型非受限名称则只使用ADL查找,然后综合第一阶段的普通查找规则进行重载解析。