在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. 使用Kotlin开发Android应用(II):创建新工程

    在基本了解什么是Kotlin以及Kotlin可以做什么之后,接下来就到了配置Android Studio并使用Kotlin开发Android apps的时候了.首次配置Android Studio需要 ...

  2. spring cloud 使用feign 遇到问题

    spring cloud 使用feign 项目的搭建 在这里就不写了,本文主要讲解在使用过程中遇到的问题以及解决办法 1:示例 @RequestMapping(value = "/gener ...

  3. Ip-san 配置过程

    1:SAN的定义 SAN是storage area network(存储区域网络)的简写,早期的san采用的是光纤通道技术,后期当iscsi协议出现以后,为了区分两者,就划分了IP SAN和FC SA ...

  4. chrome浏览器插件让你浏览github的时候像IDE一样提供项目目录

    GitHub 作为代码托管平台,竟然没有提供项目目录,方便用户在线快速浏览项目结构.所以,在线分析项目源码就会变得很繁琐,必须一层一层点击,然后再一次一次地向上返回.要知道,本来 GitHub 网站在 ...

  5. 蓝牙固件升级(OTA升级)原理设计

    转:http://blog.csdn.net/yueqian_scut/article/details/50849033 固件空中升级(OTA)与固件二次引导的原理和设计 原创 2016年03月10日 ...

  6. RocketMq入坑指南

    报错信息Caused by: org.apache.rocketmq.remoting.exception.RemotingConnectException: connect to <172.1 ...

  7. Docker容器技术-基础命令

    一.基础命令 1.运行一个镜像 [root@bogon ~]# docker run debian echo "Hello World" Unable to find image ...

  8. 标准输出:1>,2>,1>&2,2>&1

    在 shell 程式中,最常使用的 FD (file descriptor) 大概有三个, 分别是: 0 是一个文件描述符,表示标准输入(stdin)1 是一个文件描述符,表示标准输出(stdout) ...

  9. 关于form表单中button按钮自动提交问题

    坑:点击确认按钮,form表单提交2次,发送后台2次请求 //错误代码: <Button id="btnSubmit" name="btnSubmit" ...

  10. K8s ipvs mode kube-proxy

    IPVS vs. IPTABLES IPVS模式在Kubernetes 1.8中被引入,在1.9中进入beta测试. IPTABLES模式在1.1版本中被添加进来,在1.2开始就变成了默认的操作模式. ...