C++学习 9 深入STL 3

来源:互联网 发布:lol 新手 知乎 编辑:程序博客网 时间:2024/05/19 09:03
  • typename, typeid, iterator category
  • type traits , iterator traits
  • Iterator adapter, container adapter, Functor adaptor,

    typename, typeid, iterator category

    1. typename
      用法 1 在template< calss T, typename U >中用来取代class, 作用与class完全相同。
      用法 2 用于限定名中依赖模板形参 变量的声明 typedef 等。例:
      typedef typename T:: const_iterator *iter; ::表示限定名, 此处 T:: const_iterator 编译器无法预先判断是类型名, 必须加上 typename 限定。
      对于用于模板定义的依赖于模板参数的名称,只有在实例化的参数中存在这个类型名,或者这个名称前使用了typename关键字来修饰,编译器才会将该名称当成是类型。除了以上这两种情况,绝不会被当成是类型。
      这样编译器就可以确定T::iterator是一个类型,而不再需要等到实例化时期才能确定,因此消除了前面提到的歧义。

typename在下面情况下禁止使用:

    模板定义之外,即typename只能用于模板的定义中    非限定类型,比如int,vector< int>之类    基类列表中,比如template < class T> class C1 : T::InnerType不能在T::InnerType前面加typename    构造函数的初始化列表中

如果类型是依赖于模板参数的限定名,那么在它之前必须加typename(除非是基类列表,或者在类的初始化成员列表中)
其它情况下typename是可选的,也就是说对于一个不是依赖名的限定名,该名称是可选的,例如vector< int> vi;

归根结底就是判断编译器能不能 认定声明是一个类型而不是 静态数据成员、静态成员函数和嵌套类型

 struct MyClass {    static int A;    static int B();    typedef int C;}

MyClass::A, MyClass::B, MyClass::C分别对应着上面三种。
参考:http://feihu.me/blog/2014/the-origin-and-usage-of-typename/
http://pages.cs.wisc.edu/~driscoll/typename.html
http://dev.yesky.com/13/2221013.shtml
2. typeid
typeid operator 头文件 < typeinfo>
用于1.一个多态对象的动态类型已知的情况下2. 静态数据类型。
用法 typeid(type),
typeid(expression) expression引用一个具有静态存续期的左值表达式, 此表达式是或者继承于多态类型 cosnt std::type。返回结果是const type_info&。不同编译器实现的type_info class各不相同。但c++标准保证它会实现一个name()方法,该方法返回类型名字的c-style字符串。
如果表达式的类型是类类型且至少包含有一个虚函数,则typeid操作符返回表达式的动态类型,需要在运行时计算;否则,typeid操作符返回表达式的静态类型,在编译时就可以计算。
参考:http://blog.csdn.net/zkybeck_ck/article/details/51762541
https://www.zhihu.com/question/38997922/answer/79179526
cpp refernce typeid
3. iterator category
头文件< stl_iterator>

//SGI 2.9 实现如下struct input_iterator_tag {};struct output_iterator_tag {};struct forward_iterator_tag : public input_iterator_tag {};struct bidirectional_iterator_tag : public forward_iterator_tag {};struct random_access_iterator_tag : public bidirectional_iterator_tag {};

有五种类型对应迭代器定义如下:

template <class T, class Distance> struct input_iterator {  typedef input_iterator_tag iterator_category;  typedef T                  value_type;  typedef Distance           difference_type;  typedef T*                 pointer;  typedef T&                 reference;};struct output_iterator {  typedef output_iterator_tag iterator_category;  typedef void                value_type;  typedef void                difference_type;  typedef void                pointer;  typedef void                reference;};template <class T, class Distance> struct forward_iterator {  typedef forward_iterator_tag iterator_category;  typedef T                    value_type;  typedef Distance             difference_type;  typedef T*                   pointer;  typedef T&                   reference;};template <class T, class Distance> struct bidirectional_iterator {  typedef bidirectional_iterator_tag iterator_category;  typedef T                          value_type;  typedef Distance                   difference_type;  typedef T*                         pointer;  typedef T&                         reference;};template <class T, class Distance> struct random_access_iterator {  typedef random_access_iterator_tag iterator_category;  typedef T                          value_type;  typedef Distance                   difference_type;  typedef T*                         pointer;  typedef T&                         reference;};

不同容器迭代器对应 迭代器类型:
array random_access_iterator
vector random_access_iterator
list bidirectional_iterator
forward_list forward_iterator
deque random_access_iterator
set/multiset bidirectional_iterator
map/multimap bidirectional_iterator
unordered_set/unordered_multiset forward_iterator
unordered_map/unordered_multimap forward_iterator
istream_iterator input_iterator
ostream_iterator output_iterator

iterator category对算法的影响:用于指定重载类型。
例:

template <class InputIterator, class Distance>inline void __distance(InputIterator first, InputIterator last, Distance& n, input_iterator_tag) {  while (first != last) { ++first; ++n; }}template <class RandomAccessIterator, class Distance>inline void __distance(RandomAccessIterator first, RandomAccessIterator last, Distance& n, random_access_iterator_tag) {  n += last - first;}template <class InputIterator, class Distance>inline void distance(InputIterator first, InputIterator last, Distance& n) {      typedef typename iterator_traits<InputIterator>::iterator_category category;  __distance(first, last, n, category());//iterator_category(first));此为SGI2.9 实现。直接return该category 对象。与此处实现类似}

之所以只重载input 和 random_access_ietrator_tag 两种是由于除了output_iterator_access_tag 之外其余均继承于input _iterator_access_tag .是IS-A 的关系, 此处只有 random 和其他计算方式不同故只重载两种。其他的实现还有偏特化版本。
例2.

template <class InputIterator, class Distance>inline void __advance(InputIterator& i, Distance n, input_iterator_tag) {  while (n--) ++i;}#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)#pragma set woff 1183#endiftemplate <class BidirectionalIterator, class Distance>inline void __advance(BidirectionalIterator& i, Distance n,                       bidirectional_iterator_tag) {  if (n >= 0)    while (n--) ++i;  else    while (n++) --i;}#if defined(__sgi) && !defined(__GNUC__) && (_MIPS_SIM != _MIPS_SIM_ABI32)#pragma reset woff 1183#endiftemplate <class RandomAccessIterator, class Distance>inline void __advance(RandomAccessIterator& i, Distance n,                       random_access_iterator_tag) {  i += n;}template <class InputIterator, class Distance>inline void advance(InputIterator& i, Distance n) {  __advance(i, n, iterator_category(i));}

type traits , iterator traits

type traits
本质:加上一层间接性,换来以定的灵活性。通过偏特化来实现编译期类型判断, 参数传递优化等。

traits class是个类模板,在不修改一个实体(通常是数据类型或常量)的前提下,把属性和方法关联到一个编译时的实体。在c++中的具体实现方式是:首先定义一个类模板,然后进行显式特化或进行相关类型的部分特化。

我的理解是:traits是服务于泛型编程的,其目的是让模板更加通用,同时把一些细节向普通的模板用户隐藏起来。当用不同的类型去实例化一个模板时,不可避免有些类型会存在一些与众不同的属性,若考虑这些特性的话,可能会导致形成的模板不够“泛型”或是过于繁琐,而traits的作用是把这些特殊属性隐藏起来,从而实现让模板更加通用。
参考:http://blog.csdn.net/xiaoding133/article/details/7935309
http://www.cnblogs.com/pugang/archive/2012/10/17/2727378.html
http://www.cnblogs.com/youthlion/archive/2011/12/01/2255618.html
http://blog.csdn.net/xiaoding133/article/details/7930688

Iterator adapter, container adapter, Functor adaptor

  1. Iterator adapter
    insert iterators
    reverse iterators
    iostream iterators
  2. container adapter
    deque:stack、queue
    RB-tree:set、map
    参考:http://blog.csdn.net/wudaijun/article/details/14052783

  3. Functor adaptor
    通过模板类重载operator() 实现对functor的代理。
    bind,negate,compose
    头文件< functional>
    参考:http://blog.csdn.net/lanchunhui/article/details/50934031

0 0
原创粉丝点击