条款47:请使用traits classes表现类型信息——256

文章目录


我们期望的以下列方式实现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测试。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值