条款47:请使用traits classes表现类型信息
STL有五类迭代器分类,input迭代器(只读,一次,向前)、output迭代器(可写,一次,向前)、forward迭代器(读/写,多次)、Bidrectional迭代器(双向)、random access迭代器(任意跳跃,双向);
当函数、类或一些封装的通用算法的某些部分会因为数据类型不同而导致处理或逻辑不同,traits是一个很好的解决方案;traits是一种技术,它对内置类型和用户自定义类型的表现必须一样好;
实现traits技术的方法:1)确定若干你希望将来可取得的类型相关信息;2)为该信息选择一个名称;3)提供一个template和一组特化版本内含你支持的类型;实现的方式是通过if..else语句来实现(运行期判断),但是我们确定模板是在编译期,如何将这两个统一起来,方法就是重载(可以让traits classes在编译器对类型执行if..else测试);具体代码如下:
条款48:认识template元编程
TMP有两个伟大的努力,第一:它让某些事情更容易;第二,由于template metaprograms执行于C++编译器,因此可将工作从运行期转移到编译器(原先在运行期的错误,现在在编译期就能发现),导致较小的可执行文件,较短的运行期、较少的内存需要,但是导致编译期变长;
条款49:了解new-handler行为
当opertor new无法满足某一内存分配需求时,它会调用一个客户指定的错误处理函数,一个所谓的new_handle;代码如下:
new_handle是个typedef,定义一个指针指向函数,函数无参数也没有返回值;set_new_handle的参数是一个指针,指向operator new无法分配足够内存时该被调用的函数,返回值也是一个指针,指向set_new_handler被调用真在执行(马上被替换)的那个new_handler函数;
一个设计良好的new_handle函数必须做的事情有:1)分配更多内存可被使用;2)安装另外一个new_handler,如果当前的new_handle没办法处理这个事情;3)卸载new_handler,将null指针传给set_new_handle;4)抛出bad_alloc异常;5)不返回,通常调用abort( )和exit;
当这种情况牵涉到模板时,需要采用template,一种简单的做法就是建立一个“mixin”风格的base class,这种base class用来允许derive的 classes继承单一特定能力;代码如下:
代码的怪异支出在于以widget调用widget模板,这个称为怪异的循环模板模式,虽然里面继承的是模板类,但是类中却没有用到模板定义的类型,这种做法的目的只是为了让每一个class里面的static成员变量都不一样;
除了operator new之外还有一种内存分配方式,称为nothrow形式,正常分配则返还指向内存的指针,否则返回nullptr;
条款53:不要忽视编译器的警告
严肃对待编译器给出的警告,努力在你的编译器最高警告级下通过代码;
不要过渡依赖编译器,不同的编译器对待事情的态度不一样;
条款54:让自己熟悉包括TR1在内的标准程序库
C++98列入的标准程序库:STL(容器,迭代器,算法,函数对象,容器适配器,函数对象适配器),Iostream,国际化支持(多区域能力),数值处理(复数和纯数值模板),异常阶层体系,c89标准程序库;
TR1内的14个新组件:智能指针,function对象,bind绑定器,Hash tables, 正则表达式,Tuples(变量组),tr1::array,tr1::mem_fn,tr1::reference_wrapper,Typer traits,tr1::result of;
条款55:让自己熟悉boost
boost程序库对付的主题有十多个:1)字符串和文本处理;2)容器;3)函数对象和高级编程;3)泛型编程;4)模板元编程;5)数学和数值;6)正确性和测试;7)数据结构;8)语言间的支持;9)内存;10)杂项;