3 迭代器与概念和traits编程技法

3 迭代器与概念和traits编程技法

每一种STL容器都有其专属迭代器。

 

3.4 Traits编程技法——STL源代码门钥

template <class I>
struct iterator_traits{
	typedef typename I::iterator_category iterator_category;
	typedef typename I::value_type  value_type;
	typedef typename I::difference_type  difference_type;
	typedef typename I::pointer  pointer;
	typedef typename I::reference  reference;
};

template <class T>
struct iterator_traits<T*> { // 偏特化版 — 针对“迭代器是個原生指標”的情况
	typedef T value_type;
};

template <class T>
struct iterator_traits<const T*> { // 偏特化版 — 當迭代器是個 pointer-to-const
	typedef T value_type;   // 萃取出來的型別應該是T 而非const T,value_type经常用于声明局部对象,不能使const
};

template <class I>
typename iterator_traits<I>::value_type // 這㆒整行是函数返回型別
func(I ite)
{ return *ite; }

 

1、value_type

2、difference_type

template <class I, class T>
typename iterator_traits<I>::difference_type // 這㆒整行是函式回返型別
count(I first, I last, const T& value) {
	typename iterator_traits<I>::difference_type n = 0;
	for ( ; first != last; ++first)
		if (*first == value)
			++n;
	return n;
}

// 針對原生指针而設計的「偏特化(partial specialization)」版
template <class T>
struct iterator_traits<T*>{
	...
	typedef ptrdiff_t  difference_type;
};

// 針對原生的pointer-to-const而設計的「偏特化(partial specialization)」版
template <class T>
struct iterator_traits<const T*> {
	...
	typedef ptrdiff_t  difference_type;
};


3、pointer和reference

// 針對原生指標而設計的「偏特化版(partial specialization)」
template <class T>
struct iterator_traits<T*>{
	...
	typedef T*  pointer;
	typedef T& reference;
};
// 針對原生的pointer-to-const而設計的「偏特化版(partial specialization)」
template <class T>
struct iterator_traits<const T*>{
	...
	typedef const T*  pointer;
	typedef const T&  reference;
};

 

5、iterator_category

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{ };

//以advance()举例
template <class InputIterator, class Distance>
inline void __advance(InputIterator& i, Distance n, input_iterator_tag)
{
	// 單向,逐㆒前進
	while (n--) ++i;
}

// 這是㆒個單純的轉呼叫函式(trivial forwarding function)。稍後討論如何免除之。
template <class ForwardIterator, class Distance>
inline void __advance(ForwardIterator& i, Distance n, forward_iterator_tag)
{
	// 單純㆞進行轉呼叫(forwarding)
	advance(i, n, input_iterator_tag());
}
template <class BidiectionalIterator, class Distance>
inline void __advance(BidiectionalIterator& i, Distance n, bidirectional_iterator_tag)
{
	// 雙向,逐㆒前進
	if (n >= 0)
		while (n--) ++i;
	else
		while (n++) --i;
}
template <class RandomAccessIterator, class Distance>
inline void __advance(RandomAccessIterator& i, Distance n, random_access_iterator_tag)
{
	// 雙向,跳躍前進
	i += n;
}

//调用__advance(),传入的第三个参数是一个默认对象,仅仅为了使用重载机制。
template <class InputIterator, class Distance>
inline void advance(InputIterator& i, Distance n)
{
	__advance(i, n, iterator_traits<InputIterator>::iterator_category());
}

// 針對原生指標而設計的「偏特化版(partial specialization)」
template <class T>
struct iterator_traits<T*> {
...
// 注意,原生指標是㆒種Random Access Iterator
typedef random_access_iterator_tag iterator_category;
};
// 針對原生的pointer-to-const而設計的「偏特化版(partial specialization)」
template <class T>
struct iterator_traits<const T*>
...
// 注意,原生的pointer-to-const 是㆒種Random Access Iterator
typedef random_access_iterator_tag iterator_category;
};


3.5 std::iterator的保证

STL提供了一个iterator class,每个新设计的迭代器只要继承自它,就可保证STL的规范。

template <class Category,
class T,
class Distance = ptrdiff_t,
class Pointer = T*,
class Reference = T&>
struct iterator{
	typedef Category  iterator_category;
	typedef T  value_type;
	typedef Distance  difference_type;
	typedef Pointer  pointer;
	typedef Reference  reference;
};

 

3.7 SGI STL的私房菜——__type_traits

双底线前缀词是指SGI STL内部所有的东西,不在STL标准范围之内。

isterator_traits负责萃取迭代器的特性,__type_traits则负责萃取型别的特性。

struct __true_type{ };
struct __false_type{ };

template <class type>
struct __type_traits
	typedef __true_type  this_dummy_member_must_be_first;
	typedef __false_type  has_trivial_default_constructor;
	typedef __false_type  has_trivial_copy_constructor;
	typedef __false_type  has_trivial_assignment_operator;
	typedef __false_type  has_trivial_destructor;
	typedef __false_type  is_POD_type;           //Plain old data
};

/* 以㆘針對C++ 基本型別char, signed char, unsigned char, short,
unsigned short, int, unsigned int, long, unsigned long, float, double,
long double 提供特化版本。注意,每㆒個成員的值都是__true_type,表示這些
型別都可採用最快速方式(例如memcpy)來進行拷貝(copy)或賦值(assign)動
作。*/
//__STL_TEMPLATE_NULL 定义为template<>
__STL_TEMPLATE_NULLstruct __type_traits<char>{
	typedef __true_type has_trivial_default_constructor;
	typedef __true_type has_trivial_copy_constructor;
	typedef __true_type has_trivial_assignment_operator;
	typedef __true_type has_trivial_destructor;
	typedef __true_type is_POD_type;
};


举例:

template <class ForwardIterator, class Size, class T>
inline ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x) {
	return __uninitialized_fill_n(first, n, x, value_type(first));
}
template <class ForwardIterator, class Size, class T, class T1>
inline ForwardIterator __uninitialized_fill_n(ForwardIterator first,
Size n, const T& x, T1*)
{
	typedef typename __type_traits<T1>::is_POD_type is_POD;
	return __uninitialized_fill_n_aux(first, n, x, is_POD());
}

// 如果不是POD 型別,就會派送(dispatch)到這裡
template <class ForwardIterator, class Size, class T>
ForwardIterator __uninitialized_fill_n_aux(ForwardIterator first, Size n, const T& x, __false_type) {
	ForwardIterator cur = first;
	// 為求閱讀順暢簡化,以㆘將原本有的異常處理(exception handling)去除。
	for ( ; n > 0; --n, ++cur)
		construct(&*cur, x); // 見2.2.3 節
	return cur;
}

// 如果是POD 型別,就會派送(dispatch)到這裡。㆘兩行是原檔所附註解。
// 如果copy construction 等同於assignment,而且有trivial destructor,
// 以㆘就有效。
template <class ForwardIterator, class Size, class T>
inline ForwardIterator __uninitialized_fill_n_aux(ForwardIterator first, Size n, const T& x, __true_type) {
	return fill_n(first, n, x);  // 交由高階函式執行,如㆘所示。
}
// 以㆘是定義於<stl_algobase.h> ㆗的fill_n()
template <class OutputIterator, class Size, class T>
OutputIterator fill_n(OutputIterator first, Size n, const T& value) {
	for ( ; n > 0; --n, ++first)
		*first = value;
	return first;
}



        究竟一个class什么时候该有自己的non-trivial default consructor,non-trivial copy consructor,non-trivial assignment operator,non-trivial destructor呢?一个判断准则是:如果class内含指针成员,并且对它进行内存动态配置,那么这个class就需要实现自己的non-trivial-xxx。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值