- typename, typeid, iterator category
- type traits , iterator traits
Iterator adapter, container adapter, Functor adaptor,
typename, typeid, iterator category
- 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在下面情况下禁止使用:
模板定义之外,即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
#endif
template <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
#endif
template <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
- Iterator adapter
insert iterators
reverse iterators
iostream iterators container adapter
deque:stack、queue
RB-tree:set、map
参考:http://blog.csdn.net/wudaijun/article/details/14052783Functor adaptor
通过模板类重载operator() 实现对functor的代理。
bind,negate,compose
头文件< functional>
参考:http://blog.csdn.net/lanchunhui/article/details/50934031