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
    评论
STL实现萃取的方式是通过对iterator_traits进行偏特化。为了使萃取有效运行,每个都要自行以内嵌性别定义的方式定义出相应的型别。的类型萃取机制被定义为iterator_traits模板类,它接受一个类型作为模板参数,并通过特化来提取的相关信息。 在STL中,对于一般的类型,使用iterator_traits模板类进行萃取,通过的内嵌typedef来获取iterator_category、value_type、difference_type、pointer和reference等相应的型别。而针对原生指针类型的,STL会针对指针类型进行偏特化,直接定义出相应的型别,如random_access_iterator_tag、_Tp、ptrdiff_t、_Tp*和_Tp&等。这样就可以实现对的属性萃取。 通过对iterator_traits进行偏特化,STL能够根据不同的类型提取出相应的属性,从而能够在算法中正确地使用不同类型的,并根据的属性进行相应的操作。这样实现了的通用性和灵活性,使得STL算法可以适用于不同类型的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [STL---萃取](https://blog.csdn.net/jiewaikexue/article/details/111372288)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [STL 萃取](https://blog.csdn.net/qq_40080842/article/details/128112675)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值