在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. CSRF(Cross Site Request Forgery, 跨站请求伪造)

    一.CSRF 背景与介绍 CSRF(Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,它在 2007 年曾被列为互联网 20 大安全隐患之一.其他安全隐患, ...

  2. 设置linux下shell显示不同颜色的字体

    实例代码如下: #!/bin/bash clear echo -e "\033[1m Hello World" # bold effect echo -e "\033[5 ...

  3. Java进阶学习:将文件上传到七牛云中

    Java进阶学习:将文件上传到七牛云中 通过本文,我们将讲述如何利用七牛云官方SDK,将我们的本地文件传输到其存储空间中去. JavaSDK:https://developer.qiniu.com/k ...

  4. Centos(Yum源更改)

    第一步:备份你的原镜像文件,以免出错后可以恢复. [root@openstack yum.repos.d]#mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum. ...

  5. XSS插入绕过一些方式总结

    详见:http://blog.csdn.net/keepxp/article/details/52054388 1 常规插入及其绕过 1.1 Script 标签 绕过进行一次移除操作: <scr ...

  6. iOS 11 Xcode9开发 新特性学习 (新方法篇)

    1 .  引入github (1) 在Xcode 9 中,引入了 gitHub,新源代码管理导航器 可以展示branch分支和 tag标签. (2)点进去,就可以看指定一次commit了哪些东西 2 ...

  7. iOS 9 的新功能 universal links

    什么是 universal links: (通用链接) 一种能够方便的通过传统 HTTP 链接来启动 APP, 使用相同的网址打开web page和 APP的方式. 第一点,链接打开网址 顾名思义 第 ...

  8. Java中finalize()用法

    Java中finalize()   垃圾回收器要回收对象的时候,首先要调用这个类的finalize方法(你可以 写程序验证这个结论),一般的纯Java编写的Class不需要重新覆盖这个方法,因为Obj ...

  9. Python学习进程(2)Python环境的搭建

        本节主要介绍在windows和Linux平台上如何搭建Python编程环境.     (1)查看Python版本: windows: C:\Users\JMSun>python 'pyt ...

  10. 每天一个Linux命令(60)ip命令

        ip命令是Linux下较新的功能强大的网络配置工具.     (1)用法:     用法:  ip  [OPTIONS]  OBJECT  [COMMAND [ARGUMENTS]]     ...