STL——Traits编程技法

STL——Traits编程技法

偏特化的意义

如果class template拥有一个以上的template参数,我们可以针对其中某个(或数个,但非全部)参数template进行特化工作。

所谓partial specialization的意思是提供另一份template定义式,而其本身仍为templatized。《泛性思维》书中对partial specialization的定义是"针对(任何)template参数更进一步的条件限制所设计出来的一个特化版本"。

template<typename T>
class C { ... }; 			//这个泛化版本允许(接受)T为任何类型

很容易接受它有一个形式如下的 partial specialization

template<typename T>
class C<T*>{ ... };		//这个特化版本仅适用于“T为原生指针”的情况
						//“T为原生指针”便是“T为任何类型”的更进一步的条件限制		

特性萃取机

下面这个class template专门用来“萃取”迭代器的特性,而value type正是迭代器的特性之一

template<class T>
struct iterator_traits{			//traits意为“特性”
    typedef typename I::value_type	value_type;
};

这个所谓的traits,其意义是,如果 I定义有自己的value type,通过这个traits的作用,萃取出来的value_type就是I::value_type

在这里插入图片描述

图上说明traits所扮演的“特性萃取机”角色,萃取各个迭代器的特性,这个迭代器特性,指的是迭代器的相应型别。

最常用的迭代器相应型别有五种:value type,difference type,pointer,reference,iterator catagory。

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

value_type

所谓value type,就是指迭代器所指对象的类型。

difference type

difference type用来表示两个迭代器之间的距离,因此它可以用来表示一个容器的最大容量。对于连续空间的容器而言,头尾之间的距离就是其最大容量。如果一个泛型算法提供计数功能,例如count(),其传回值就必须适用迭代器的difference_type

reference type

迭代器所引用的类型

int* pi = new int(5);
const int* pci = new int(9);
*pi = 7;		//对mutable iterator进行解引用操作时,获得的应该是左值,允许赋值
*pci = 1;		//这个操作不允许,因为pci是一个constant iterator

如果p是一个constant iterator,其value typeT,那么*p的型别不应该是const T,而是const T&。如果pmutable iterator时,如果其value typeT,那么*p的类型是T&

pointer type

迭代器所指的类型

template<class T>
struct iterator_traits{
    ...
    typedef typename I::pointer pointer;
    typedef typename I::reference reference;
}
//针对原生指针而设计的“偏特化版”
template<class T>
struct iterator_traits<T*>
{
    ...
    typedef T* pointer;
    typedef T& reference;
};
//针对原生的pointer-to-const而设计的“偏特化版”
struct iterator_traits<const T*>
{
    ...
	typedef const T* pointer;
    typedef const T& reference;
};

iterator_category

迭代器所属的类别

input_iterator,output_iterator,forward iterator,bidirectional iterator,random access iterator;

template<class T>
struct iterator_traits{
    ...
    typedef typename I::iterator_category iterator_category;
}
//针对原生指针而设计的“偏特化版”
template<class T>
struct iterator_traits<T*>
{
    ...
    typedef =random_access_iterator_tag iterator_category;
};
//针对原生的pointer-to-const而设计的“偏特化版”
struct iterator_traits<const T*>
{
    ...
	typedef =random_access_iterator_tag iterator_category;
};

iterator源代码

//5种迭代器类型
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 bidireactional_iterator_tag {};

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

//榨汁机traits
template<class Iterator>
struct iterator_traits{
    typedef typename Iterator::iterator_category iterator_category;
    typedef typename Iterator::value_type value_type;
    typedef typename Iterator::difference_type difference;
    typedef typename Iterator::pointer pointer;
    typedef typename Iterator::reference reference;
};

//针对原生指针而设计的traits偏特化版
template<class T>
struct iterator_traits<T*>{
    typedef typename random_access_iterator_tag iterator_category;
    typedef typename T value_type;
    typedef typename ptrdiff_t difference;
    typedef typename T* pointer;
    typedef typename T& reference;
};

//针对原生指针而设计的traits偏特化版
template<class T>
struct iterator_traits<const T*>{
    typedef typename random_access_iterator_tag iterator_category;
    typedef typename T value_type;
    typedef typename ptrdiff_t difference;
    typedef typename T* pointer;
    typedef typename T& reference;
};

//这个函数可以很方便的决定某个迭代器的类型(category)
template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&){
    typedef typename iterator_traits<Iterator>::iterator_category category;
    return category();
}

//这个函数可以很方便的决定某个迭代器的distance type
template <class Iterator>
inline typename iterator_traits<Iterator>::difference_type*
distance_type(const Iterator&){
    return static_cast<typename iterator_traits<Iterator>::difference_type*>(0);
}

//这个函数可以很方便的决定某个迭代器的value type
template <class Iterator>
inline typename iterator_traits<Iterator>::difference_type*
distance_type(const Iterator&){
    return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
}

type_traits

type_traits负责萃取类型的特性。此处我们所关注的类型特性是指:这个类型是否具备 non-trivial defalt ctor(默认构造函数),non-trivial copy ctor(拷贝构造函数),non-trivial assignment operator(拷贝赋值运算符)和 non-trivial dtor(析构函数)。如果答案是否定的,我们在对这个类型进行构造,析构,拷贝,赋值等操作时,就可以采用最有效率的措施,采用内存直接处理操作如malloc,memcpy等等,获得最高效率。

在程序中,可以这样运用__type_traits<T>T代表任意类型。

__type_traits<T>::has_trivial_default_constructor;
__type_traits<T>::has_trivial_copy_constructor;
__type_traits<T>::has_trivial_assignment_operator;
__type_traits<T>::has_trivial_destructor;
__type_traits<T>::is_POD_type;

上述式子响应“真”或“假”,但结果不应该只是个bool值,应该是个有着真/假性质的“对象”,因为我们希望可以利用其返回结果进行参数推导,而编译器只有面对class object形式的参数,才会做参数推导。为此,上述式子应该传回这样的东西;

struct __true_type {};
struct __false_type {};

对于某些类型

__STL_TEMPLATE_NULL struct __type_traits<int>
{
    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;
};
__STL_TEMPLATE_NULL struct __type_traits<long>
{
    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;
};
__STL_TEMPLATE_NULL struct __type_traits<float>
{
    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;
};
__STL_TEMPLATE_NULL struct __type_traits<double>
{
    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;
};
//针对原生指针而设计__type_traits“偏特化版”
template<class T>
struct __type_traits<T*>
{
    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;
};

如果我们定义了一个Shape类,也可以针对这个Shape设计type_traits的特化版本。

template<> struct __type_traits<Shape>{
    typedef __true_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;
};
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值