在stl的算法中,我们的希望往往是根据不同的迭代器类型进行不同的更有效率的操作:

 template<typename IterT, typename DistT>
void advance(IterT iter, DistT dis)
{
if(iter is a random access iterator)
iter += dis;
else{
if(dis >= ){
while(dis--)
iter++;
}else{
while(dis++)
iter--;
}
}
};

这种可以识别Iterator类别的技术叫做iterator_traits,首先起要求每一个用户自定义的迭代器类型都应该有个typedef,类似下面这样:

 template<...>
class list{
public:
class iterator{
typedef typename bidirectional_iterator_tag iterator_category;
...
};
};

这样iterator_traits就可以通过萃取技术将迭代器的类型给萃取出来:

 template<typename IterT>
struct iterator_traits
{
typedef typename IterT::iterator_category iterator_category;
...
};
上述的技术可能对指针来书的行不通的,因为指针无法内置的去指定iteartor_catagory;
只能通过模板的特化去解决这个问题:

 tempalte<typename IterT>
struct iterator_traits<IterT *>
{
typedef random_access_iterator_tag iterator_category;
...
};

有了iterator_traits技术以后,实现有效率的迭代就是可能的了。但是实际上不是通过 if Iterator is a random_access_iterator这种形式来实现的,而是通过函数的重载来实现的:

 template<typename IterT, typename DistT>
doAdvance(IterT iter, DistT d, std::random_access_iterator_tag)//这里的tag往往先通过iterator_traits进行萃取而得到的;
{
iter += d;
}
template<typename IterT, typename DistT>
doAdvance(IterT iter, DistT d, std::bidirectional_iterator_tag)
{
if(dis >= ){
while(dis--)
iter++;
}else
while(dis++)
iter--;
}
tempalte<typename IterT, typename DistT>
doAdvance(IterT iter, DistT d, std::input_iterator_tag) //注意这里的迭代器版本
{
if(d < )
throw std::out_of_range("Negetive distance!");
else{
while(d--) ++iter;
}
}
上面最后一个版本的doAdvanced实际上是input_iterator版本,但由于forward_iterator_tag是继承与于input_iterator_tag的,所以这里的doAdvance同样可以对前向迭代器进行处理。
由上面的不同版本的iterator实际上就可以写出advance的实现版本了:

 template<typename IterT, typename DistT>
doAdvance(IterT iter, DistT d)
{
doAdvance(iter, d,
typename std::iterator_traits<IterT>::iterator_category()); //注意这里使用到了typename
}
所以说一个traits class实际上相当于:
    建立一组h重载函数或者是函数模板,彼此间的差异仅仅在于各自的traits参数。
    建立一个控制函数或者模板函数,起调用上面的模板函数并且传递traits信息。
 
小结:
    trait_class使得类型的相关信息在编译期就是可用的,其以template以及template的特例化来完成。
    整合重载机制一起,traits_class可能可以在编译期就对类型执行if-else测试。

条款47:请使用traits class表示类型信息的更多相关文章

  1. Effective C++ Item 47 请使用 traits classes 表现类型信息

    本文为senlie原创.转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:Traits classes 使得"类型相关信息"在编译期可用.它 ...

  2. Effective C++ -----条款47:请使用traits classes表现类型信息

    Traits classes使得“类型相关信息”在编译期可用.它们以template和“templates特化”完成实现. 整合重载技术(overloading)后,traits classes有可能 ...

  3. 【47】请使用traits classes表现类型信息

    1.考虑下面的需求,对迭代器移动d个单位.因为不同类型的迭代器,能力不同,有的迭代器(vector,deque内置迭代器)可以一步到位移动到指定位置,有的迭代器(list内置迭代器)必须一步一步移动, ...

  4. 读书笔记 effective c++ Item 47 使用traits class表示类型信息

    STL主要由为容器,迭代器和算法创建的模板组成,但是也有一些功能模板.其中之一叫做advance.Advance将一个指定的迭代器移动指定的距离: template<typename IterT ...

  5. EC读书笔记系列之18:条款47、48

    条款47 请使用traits classes表现类型信息 记住: ★Traits classes使得“类型相关信息”在编译期可用.它们以templates和“templates特化”完成实现 ★整合重 ...

  6. 读书笔记_Effective_C++_条款四十七:请使用trait classes来表示类型信息

    这一条款主要来讨论模板中迭代器的属性iterator_category,它可以通过类似于vector<int>::iterator::iterator_category的方式来取得. 到这 ...

  7. .NET 错误 47 存储区提供程序工厂类型“Oracle.DataAccess.Client.OracleClientFactory”未实现 IServiceProvider 接口。请使用实现该接口的存储区提供程序。

    问题描述: 最近用VS2010连接ORACLE数据库的时候突然报错“错误 47 存储区提供程序工厂类型“Oracle.DataAccess.Client.OracleClientFactory”未实现 ...

  8. Effective C++ 条款47

    本节条款的题目:请使用trait classes来表示类型信息 本节条款主要讲述的技术是怎样在编译期间实现对迭代器类型的推断,依据推断的类型进行最优处理. 我们先来看一下迭代器的种类: 1.input ...

  9. Java基础 -- 深入理解Java类型信息(Class对象)与反射机制

    一 RTTI概念 认识Claa对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RT ...

随机推荐

  1. 0402-服务注册与发现-Eureka Server使用、将服务注册到Eureka server上

    一.Eureka Server使用 官方文档地址:http://cloud.spring.io/spring-cloud-static/Edgware.SR3/single/spring-cloud. ...

  2. net mvc 利用NPOI导入导出excel

    1.导出Excel : 首先引用NPOI包(Action一定要用FileResult) /// <summary> /// 批量导出需要导出的列表 /// </summary> ...

  3. Oracle处理Clob类型数据入库(String入库)

    从网上查找一堆参考,要么语焉不详,要么不可行.自己鼓捣了一堆可以正常入库了.请看最后: insert into CP_V_INFO" + "(ID, "+ "P ...

  4. 分层架构下的纯JDBC事务控制简单解决方案【转】

    http://blog.csdn.net/qjyong/article/details/5464835 对目前的JavaEE企业应用开发来说,基本都会采用分层的架构, 这样可以分散关注.松散耦合.逻辑 ...

  5. 【整理学习Hadoop】Hadoop学习基础之二:分布式

      分布式系统就是将系统的应用层,数据层或其它部分构架成分布(物理和逻辑上的都可以)状(通常是网状).分布式系统通常是为了增强系统的可扩展性.稳定性和执行效率.比如在线游戏通常就是分布系统,里面所谓的 ...

  6. bacula 备份恢复

    一.数据恢复: 在bacula服务器执行: /opt/bacula/etc/ bconsole #进入交互窗口 *restore #输入restore恢复命令 Automatically select ...

  7. Kattis - sortofsorting 【排序】

    题意 给出一系列字符串,然后要排序 排序规则 只按前两位按字典序来排序,如果前两位完全一样,则按输入的顺序来排 思路 要用 冒泡排序 不能用STL里面的 SORT 因为它不稳定 AC代码 #inclu ...

  8. iOS 事件响应者链的学习(也有叫 UI连锁链)

    当发生事件响应的时候,必须知道由谁来响应事件.在iOS中,由响应链来对事件进行响应,所有的事件响应的类都是继承于UIResponder的子类,响应链是一个由不同对象组成的层次结构,其中每个对象将依次获 ...

  9. MySQL密码的恢复方法

    MySQL密码的恢复方法之一 1.首先确认服务器出于安全的状态,也就是没有人能够任意地连接MySQL数据库. 因为在重新设置MySQL的root密码的期间,MySQL数据库完全出于没有密码保护的 状态 ...

  10. Linux的XServer

    Moblin Core是在Gnome Mobile的平台上建立.我以前玩Linux,提交的都和图像没有关系,连Xwindows都不用启动,开机后直接进入文本命令行,所以这方面了解得很少,需要学习一下, ...