文章目录
我们期望的以下列方式实现advance:
template<typename IterT,typename DistT>
void advace(IterT& iter,DistT d)
{
if(iter is a random access iterator)
{
iter+=d; //针对random access迭代器使用迭代器算术运算
}
else {
if(d>=0){while(d--) ++iter;} //针对其他迭代器分类,反复调用++或--
else {while(d++) --iter;}
}
}
这种做法首先必须判断iter是否为random access迭代器,那就是traits让你得以进行的事:它们允许你在编译期间取得某些类型信息。
Traits是一种技术,这个技术的要求之一是:它对内置(build-in)类型和用户自定义类型的表现必须一样好。
“Traits必须能够施行于内置类型”意味“类型内的嵌套信息”这种东西出局了,因为我们无法将信息嵌套于原始指针内。因此类型的traints信息必须位于类型自身之外。标准技术是把它放进一个template及其一或多个版本。
设计并实现一个traints class:
(1)确认若干你希望将来可取得的类型相关信息。
(2)为该信息选择一个名称。
(3)提供一个template和一组特化版本,内含你希望支持的类型相关信息。
我们再来具体实现advace:
template<typename IterI,typename DistT> //这份实现用于random access迭代器
void doAdvance(IterT& iter,DistT d,std::random_access_iterator_tag)
{
iter += d;
}
template<typename IterI,typename DistT> //这份实现用于bidirectional迭代器
void doAdvance(IterT& iter,DistT d,std::bidirectional_iterator_tag)
{
if(d>=0){while(d--) ++iter;}
else {while (d++) --iter;}
}
template<typename IterI,typename DistT> //这份实现用于input迭代器
void doAdvance(IterT& iter,DistT d,std::input_iterator_tag)
{
if(d<0){
throw std::out_of_range("Negative distance");
}
while(d--) ++iter;
}
... //forward迭代器也可以用于input_iterator_tag的版本
template<typename IterT,typename DistT>
void advance(IterT& iter,DistT d)
{
doAdvace(
iter,d,
typename
std::iterator_traits<IterT>::iterator_category()
);
}
其中详细设计还是看原文才能深刻理解
总结——262
(1)Traits classes使得“类型相关信息”在编译器可用。它们以templates和“templates特化”完成实现。
(2)整合重载技术(overloading)后,traits classes有可能在编译期对类型执行if…else测试。