STL学习笔记(traits编程技法)

为了完成一个迭代器,我们往往会把容器实现的太多细节暴露在外面,于是干脆把迭代器的开发交予容器设计者,如此一来所有的实现细节便能不被使用者所见,实现了封装。

为了使泛型算法使用迭代器,可能会使用到相应型别(associated type),【这里指的是迭代器所指之物的型别】。而C++本身不支持typeof(),RTT的typeid()获得的也只是类型名称而不能拿来做变量声明。

解决办法function template的参数推导(argument deduction)机制。(STL源码剖析page85)

参数推导机制可以解决迭代器的value type,但一旦valuetype必须用于函数的传回值变束手无策了(template参数推导机制推而导之的只是参数,无法推导函数的返回值型别)。

解决办法声明内嵌类型(STL源码剖析page86)

但是存在一个隐晦的陷阱,不是所有的迭代器都是class type,比如原生指针,她无法定义为内嵌型别。

解决办法:针对特殊情况做特殊化处理,使用template partial specialization(类模板偏特化),

【附注】所谓偏特化不是指对模板参数的个别指定,而是提供另一份template,而其本身仍为templatized

正式进入trait技法。

value type是迭代器的特性之一,迭代器还拥有其他特性,故使用专门的类将其封装。统一作为迭代器型别的“榨汁机”-------iterator_traits(原生指针和const类型使用偏特化)

template<class I>
struct iterator_traits
{
	typedef typename I::iterator_category iterator_category;  //为了使编译器能够识别,使用typename声明其为一个型别
	typedef typename I::value_type value_type;                   //而非class function member or data member
	typedef typename I::different_type different_type;
	typedef typename I::pointer pointer;
	typedef typename I::reference reference;
};

为了使traits可以正常使用, 每一个迭代器必须遵守约定,自行已内嵌型别定义的方式定义相应型别,否则自别与STL这个大家庭。

然后为原生指针和const类型偏特化(const“萃取”后为右值,特化其为萃取左值)【STL源码剖析page90-94】

在具体的算法里还需要进一步的封装【page93-99有例子】

一些零碎的笔记:

在C++中,函数如果要传回左值,都是已by reference的方式进行的。

在研究STL中,我们一定要谨记效率是个重要的课题。

命名规则:只在程序内部使用的函数加前导符(_advanced())

命名规则:STL算法所能接受的最低阶迭代器作为迭代器型别的参数命名

STL规范:任何迭代器都应该提供五个内嵌相应型别


总结:

设计适当的相应型别,是迭代器的责任,设计适当的迭代器,是容器的责任,,只有容器本身,才知道该设计怎样到迭代器遍历自己,执行迭代器该有的各种行为,至于算法,只要设计时以迭代器为对外接口就行。

traits利用内嵌型别的编程技巧与编译器的template参数推导功能弥补了C++未能提供的型别认证方面的能力。


参考资料:

《STL源码剖析》

《C++ primer》


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值