STL源码剖析笔记第三章

第三章

3.4 traits

iterator_traits<T>

为了获取iterator所指内容的型别,有了iterator_traits
my_define.h

#ifndef CH1_MY_DEFINE_H
#define CH1_MY_DEFINE_H
template<class T>
struct my_iterator_traits{
    typedef typename T::value_type value_type;

};

template<class T>
struct my_iterator_traits<T*>{
    typedef  T value_type;

};


#endif //CH1_MY_DEFINE_H

这里使用了偏特化。限定了T必须为指针类型。

template<class T>
struct my_iterator_traits<T*>{
    typedef  T value_type;
};

基于此,可以对指向const T 的指针(pointer to const)也加以偏特化。(因为希望萃取出来的value_typeT而不是const T

template<class T>
struct my_iterator_traits<const T*>{
    typedef  T value_type;
};

main.cpp

#include <iostream>
#include <vector>

#include "my_define.h"


using namespace std;

template<class I>
typename my_iterator_traits<I>::value_type 
function(I a) {
    return *a;
}

int main() {
    int *aa = new int;
    *aa = 1;
    cout<< function(aa)<<endl;
    int a = 1;
    vector<int> arr(1,0);
    auto iter=arr.begin();
    cout<< function(iter)<<endl;
    return 0;
}

iterator_category

因为有不同的数据结构,那么对使用迭代器遍历时会有不同的效率。正如书中所说,若能萃取出迭代器类型,就能执行与它最匹配的迭代器移动方法。

最基础的想法是,用一个函数专门完成转发。

template<class InputIterator,class Distance >
void advance(InputIterator& i,Distance n) {
	if(is_random_access_iterator(i)) {
		//balabala...
	} else if(is_bidirectional_iterator(i)) {
		//balabala...
	} else {
		// ...
	};
};

但是在执行时期才决定使用哪一个版本,拉跨效率。
于是要是能把迭代器类型作为参数传入就好了。
于是使用了class来代表五种迭代器类型

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 >
void advance(InputIterator& i,Distance n) {
	__advance(i,n,
			  	iterator_traits<InputIterator>::iterator_category(i));
};

iterator_category()

并有如下获取迭代器类型的函数

template<class T>
inline typename iterator_traits<T>::iterator_category
iterator_category(const I&) {
	typedef typename iterator_traits<T>::iterator_category category;
	return category();//返回一个category临时对象。但由于是空struct,应该是无负担的
}

value_type()

template<class Iterator>
inline typename iterator_traits<Iterator>::value_type*
value_type(const Iterator&) {
	return static_cast<typename 
						iterator_traits<Iterator>::value_type*>(0);
}

static_cast使用

__type_traits<T>

__type_traits<T>用于提取迭代器型别的特性。据书所述,主要是区分是不是POD(Plain Old Data)型别。
POD型别

struct __true_type {};
struct __false_type {};

那么之后这样定义就可以了。

template<class type>
struct __type_traits {
	typedef __true_type this_dummy_member_must_be_first;
	/*没看懂书中注释说的啥...*/
	//全部定义为false,保守起见。
	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;

很tricky,之后对基本scalar类型再定义一份特化版本就好了。比如

template<>
struct __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;

省略一万个类型…

总结

总的来说,使用一个class来作为tag标记,有点出乎意料(是我太菜了。。)开启了新世界的大门…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值