C++ template笔记若干

本文详细探讨了C++模板的多个方面,包括编译器的实参演绎、类模板的默认参数、函数模板的限制、非类型模板参数的规则、ODR原则、SFINAE原理、ADL机制、依赖型名称以及模板的特化与重载。同时,还讨论了动多态与静多态、trait和policy类、元编程以及表达式模板等高级主题。
摘要由CSDN通过智能技术生成

1.调用函数模板时,可以通过编译器进行实参演绎(/deduction/推导)而不必显式指定实参类型。但是必须严格匹配。
 *:在非引用类型参数中,数组类型将会decay成对应指针类型,而引用类型则不会。
 即引用类型参数中,"hi"和"abc"是不同的类型(const char[3]和const char[4])。解决这个问题可以改用非引用类型,不过最好是针对需要用的数组类型进行特化。
2。类模板参数可以定义缺省值,且只有那些被调用的成员函数才会被实例化。
3。类模板中的函数模板不能是虚函数,但非模板的函数可以。
4。非类型模板参数(即常数参数)不能使用浮点数(历史原因),class类型,以及内部链接对象(可以用extern char const s[]="hi";MyClass<s> x;但去掉extern后就不行。),但可以使用外部链接的指针常量或引用。(当实参匹配最后一种类型时,除加上const或volatitle的隐式转换外所有隐式转换或用户自定义转换均无效。)

 

ODR:(通常情况)
1。全局变量、静态数据成员,非内联函数、成员函数在整个程序中只能被定义一次。
2。class类型和内联函数在每个翻译单元中只能被定义一次。

 

SFINAE(substitution-failure-is-not-an-error):
当用某一实参类型替换一个函数重载中的类型参数会导致替换失败时,只要这个函数有一个重载可以替换成功,就不认为这是错误。这个特性可以用于RTTI以及反射。但是,这里的替换失败指的是因为无效的类型而失败,如果是因为无效的表达式而失败(如除0),则不属于SFINAE保护的范围。

 

受限名称(qualified name):用一个类名或命名空间或全局作用域解析符进行了限定了的名称,或使用了成员访问运算符(./->)的名称。

依赖型名称(dependent name):以某种形式依赖于模板参数的名称。包括显式使用模板参数的名称、对依赖性名称使用成员访问运算符(./->)获得的名称,对于在模板中出现的this->b中的b,型如f(a,b,c)的调用并且abc其中有一个是依赖型名称中的f。

ADL(arument-dependent lookup):为了解决在另一个命名空间定义的类型也能使用模板的问题。(或者说模板使用时,不会查找使用模板的类型所在的命名空间中的函数或定义的问题)
应用范围:非受限名称。对于成员函数或名称,如果普通查找能找到函数,将不会应用ADL。

大致查找流程:依次查找每个实参的关联类(associated class)和关联命名空间。
关联类和关联命名空间大致可以认为是与给定类型直接相关的所有类和命名空间。
比如类类型,它的关联类包括这个class类型本身,它的外围类型,它的所有基类型。如果这个类是一个类模板的实例(即使用ADL的这个函数使用了模板的模板参数),那还包括这个实例所用的模板实参类型,声明模板的模板实参所在的class和命名空间。
又比如类X的成员指针类型,除了这个成员的类型的关联类和命名空间,还包括X相关的关联类和命名空间。
注意:基本类型的关联类和关联命名空间为空。

*:不要试图在没有使用using的情况下使用ADL找到位于另一个命名空间的模板函数。
如在命名空间N定义了<int I>f(C*)模板,和类C,那么在另一个命名空间中,没有使用using引入f模板时
void g(N::C* xp){f<3>(xp);}将是无效的。
因为此时只有知道f<3>是一个模板时,才知道f<3>(xp)是一个函数调用(即xp是一个函数实参),这才能使用ADL,而当不知道xp是一个函数实参时,自然没有使用ADL,也就不知道f<3>是一个模板。最后语句解析成
(f<3) > (xp);
而这显然不是我们期望的。

 

依赖型类型名称:
一个在模板内出现的类型名称,如果该名称是受限的,且依赖于模板参数,则需要在其前面加关键字typename表示它是一个类型。但是在指定继承的基类列表中,以及构造函数的初始化列表中不能因此加typename关键字。(但是初始化列表中的初始化语句如果遇到这种情况则需要加typename)
示例:

template < typename T >
struct  S : X < T > ::Base {
 S() : X
<T>::Base(typename X<T>::Base(0) ){}
 X
<T> f(){
  typename X
<T>::C *p; //define of point p;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值