前一篇文章《浅谈C++ templates 函数模板、类模板以及非类型模板参数》简单的介绍了什么是函数模板(这个最简单),类模板以及非类型模板参数。本文对类模板再做几点补充。
文章目录
1. 缺省的模板实参2. Traits编程技法——以STL迭代器为例1. 缺省的模板实参这里依旧使用上一篇文章中的array类作为例子,其中有一处改变了——就是将unsigned int N = 10后面添加了一个默认的参数10:template<typename T, unsigned int N = 10>
class array { public: array(); T& operator[] (unsigned int index); constexpr unsigned int size() noexcept;private: T elems[N]; int length;正是由于有默认的参数,所以如果没有指定array的大小的话,就会默认为10。og::array<int> ai;
ai[0] = 4;ai[2] = 123;//ai[11] = 666; //exception以上,并没有指定array大小为默认值10,所以ai[11]就出错了。2. Traits编程技法——以STL迭代器为例
Traits技法主要是利用了“内嵌类型”的技巧,加上一部分编译器template参数推导的功能。能力十分强劲。咯,这里给出了一个迭代器的基类,让我们看一下STL是如何施展Traits技法的。template <typename Category,
typename T, typename Distance = ptrdiff_t, typename Pointer = T*, typename Reference = T&>class iterator {//iterator basepublic: typedef Category iterator_category; typedef T value_type; typedef Distance difference_type; typedef Pointer pointer; typedef Reference reference;下面开始使用class template“萃取”迭代器的特性,直接祭出3个萃取器,我将它们命名为:main trait、pointer trait和pointer-to-const trait。template <typename I>
class iterator_traits {//main trait typedef typename I::iterator_category iterator_category; typedef typename I::value_type value_type; typedef typename I::difference_www.xgll521.com type difference_type; typedef typename I::pointer pointer; typedef typename I::reference reference;};template <typename I>
class iterator_traits<I*> {//pointer trait typedef typename I::iterator_category iterator_category; typedef typename I::value_type value_type; typedef typename ptrdiff_www.thd178.com t difference_type; typedef typename I* pointer; typedef typename I& reference;};template <typename I>
class iterator_traits<const I*> {//pointer-to-const trait typedef typename I::iterator_category iterator_category; typedef typename I::value_type value_type; typedef typename ptrdiff_t difference_type; typedef typename I* pointer; typedef typename I& www.gcyl152.com reference;以上,你可能有两点疑惑。其一,class iterator_traits<I*>这样的写法?这种其实叫做类模板的特化,第一个main trait被称为基本模板,后面的两个则为局部特化模板。我试了,必须要有基本模板,才能有局部特化模板,否则语法报错。
其二,类似于typedef typename I::pointer pointer;这样的写法?这里有两小点需要解释:
No.1 I::pointer 这里其实要求typename I传进来的必须是iterator base类,这样才能直接取类中的public成员变量。
No.2 我们常见的为typedef unsigned int size_t这样的写法?对typename balabala…的很不熟悉,这里举个例子你就熟悉了:
typedef struct node{
int data; struct node* next;}node_t;node_t n1;
是不是有异曲同工之妙?好了,开始另外一个话题—— 如何利用迭代器在编译时推断出类型?
直接看例子吧!这个函数可以很方便地决定某个迭代器的value_type。
template <typename Iterator>
inline typename iterator_traits<www.ysyl157.com Iterator>yongshiyule178.com::value_type* //返回值类型value_type(const Iterator&) { return static_cast<typename iterator_traits<Iterator>::value_type*>(0);}