在stl的算法中运用容器的迭代器时,很可能经常会用到迭代器相应型别(例如迭代器所指物的型别),假设算法中有必要声明一个变量,以“迭代器所指对象的型别”为类型,如何是好,例如我们写一个功能,打印迭代器元素的值:

template <class T>
struct MyIter
{
typedef T value_type;
T* ptr;
MyIter(T* p = NULL):ptr(p){}
T& operator*()const {return *ptr;}
}; template <class T>
typename T::value_type func(T iter)
{
return *iter;
} int main()
{
MyIter<int> ite(new int());
printf("%d", func(ite));
return ;
}

但是我们无法支持原生指针,比如

int a = 10;

int b = func(&a);

这里偏特化可以帮我们实现,"所谓partial specialization"的意思就是提供另一份template的定义式,而其本身仍为templatized”。

“针对(任何)template 参数更进一步的条件限制所设计出来的一个特化版本”——《泛型思维》

第一步定义iterator_traits中间层:

template <class T>
struct MyIter
{
typedef T value_type;
T* ptr;
MyIter(T* p = NULL):ptr(p){}
T& operator*()const {return *ptr;}
}; //针对带内嵌类型的迭代器
template <class I>
struct iterator_traits
{
typedef typename I::value_type value_type;
}; template <class T>
typename iterator_traits<T>::value_type func(T iter)
{
return *iter;
} int main()
{
MyIter<int> ite(new int());
printf("%d", func(ite)); return ;
}

输出:8

第二步,针对原生指针设计一个特化版本:

template <class T>
struct MyIter
{
typedef T value_type;
T* ptr;
MyIter(T* p = NULL):ptr(p){}
T& operator*()const {return *ptr;}
}; //针对带内嵌类型的迭代器
template <class I>
struct iterator_traits
{
typedef typename I::value_type value_type;
}; //针对原生指针
template <class I>
struct iterator_traits<I*>
{
typedef I value_type;
}; template <class T>
typename iterator_traits<T>::value_type func(T iter)
{
return *iter;
} int main()
{
MyIter<int> ite(new int());
printf("%d\n", func(ite));
int a = 1;
printf("%d\n", func(&a));
return ;
}

但是假设我在func里面希望做如下操作:

template <class T>
typename iterator_traits<T>::value_type func(T iter)
{
  typename iterator_traits<T>::value_type a;
  a++;   //这里将报错,const 常量无法修改
  return *iter;
}

我们希望的效果是:只想定义一个T类型的数据类型,如果需要const修饰,我们自己在类型前面加个const即可。

于是我们还要对const T*设计一个特化版本:

template <class T>
struct MyIter
{
typedef T value_type;
T* ptr;
MyIter(T* p = NULL):ptr(p){}
T& operator*()const {return *ptr;}
}; //针对带内嵌类型的迭代器
template <class I>
struct iterator_traits
{
typedef typename I::value_type value_type;
}; //针对原生指针
template <class I>
struct iterator_traits<I*>
{
typedef I value_type;
};
//针对const原生指针
template <class I>
struct iterator_traits<const I*>
{
typedef I value_type;
}; template <class T>
typename iterator_traits<T>::value_type func(T iter)
{
typename iterator_traits<T>::value_type a;
a++;
return *iter;
} int main()
{
MyIter<int> ite(new int());
printf("%d\n", func(ite));
int a = ;
const int* pa = &a;
func(pa); return ;
}

STL迭代器之一:偏特化的更多相关文章

  1. C++的模板特化 和 STL中iterator_traits模板的偏特化

    C++中有类模板和函数模板,它们的定义如下所示: 类模板: template<class T1,class T2> class C { //... }; 函数模板: template< ...

  2. [C++ 2011 STL (VS2012 Update4) 源代码阅读系列(2)]熟悉一些宏定义和模版偏特化或叫模版专门化

    [C++ 2011 STL (VS2012 Update4) 源代码阅读系列(2)]熟悉一些宏定义和模版偏特化或叫模版专门化 // point_test.cpp : 知识点练习和测试,用于单步调试,跟 ...

  3. STL 全特化/偏特化

    template<class T> class Compare { public: static bool isEqual(const T& lh,const T& rh) ...

  4. STL全特化与偏特化

    在泛型编程中,常常会使用一些非完全泛型的类模板,这就是特化. 如何理解全特化呢?如上图所示,第一个template class是空间配置器的类模板,第二个就是一个全特化的template class. ...

  5. stl迭代器原理

    具体实现肯定不如书上讲的清楚了,这里只是根据侯捷书上的讲解,自己建立一条思路以及形成一些相关的概念 迭代器也可被称作智能指针,用于遍历容器内的元素,stl每个容器都实现了自己的iterator,ite ...

  6. [转]Traits 编程技法+模板偏特化+template参数推导+内嵌型别编程技巧

    STL中,traits编程技法得到了很大的应用,了解这个,才能一窥STL奥妙所在. 先将自己所理解的记录如下: Traits技术可以用来获得一个 类型 的相关信息的. 首先假如有以下一个泛型的迭代器类 ...

  7. 一步一步的理解C++STL迭代器

    一步一步的理解C++STL迭代器 "指针"对全部C/C++的程序猿来说,一点都不陌生. 在接触到C语言中的malloc函数和C++中的new函数后.我们也知道这两个函数返回的都是一 ...

  8. STL——迭代器与traits编程技法

    一.迭代器 1. 迭代器设计思维——STL关键所在 在<Design Patterns>一书中对iterator模式定义如下:提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素 ...

  9. oop &&GP 模板 ---> 特化和偏特化

    OOP面向对象编程 GP泛型编程(generic programming) 两者的主要区别就是OOP将数据和对数据的操作放在一起, GP就是将数据和操作独立开来 GP:   数据就是container ...

随机推荐

  1. ubuntu系统lamp环境搭建、数据库迁移、设置数据库外部访问

    sudo passwd root设置两次密码su输入设置的密码exit (退出root帐号) 1.sudo apt-get update 2.sudo apt-get install apache2 ...

  2. powerdesinger

    www.sap.com solutions>data management>powerdesinger http://www.sap.com/product/data-mgmt/power ...

  3. 使用Spring缓存的简单Demo

    使用Spring缓存的简单Demo 1. 首先创建Maven工程,在Pom中配置 <dependency> <groupId>org.springframework</g ...

  4. Who is using Asio?

    https://think-async.com/Asio/WhoIsUsingAsio

  5. IOS开发-图片上传

    目前IOS端开发,图片上传到服务器分为两种,一种是直接上到服务器,一种是借助第三方储存(减少服务器压力). 一.直接上传到服务器 /** * 代码演示 */ //*******UIImagePNGRe ...

  6. 升级Dell的R810固件版本

    1.到下面链接去下载win32版本的EXE固件 http://www.dell.com/support/home/cn/zh/cndhs1/Drivers/DriversDetails?driverI ...

  7. python---map,filter,reduce

    map 遍历序列,对序列中每个元素进行操作,最终获取新的序列. li = [11, 22, 33] new_list = map(lambda a: a + 100, li) #new_list = ...

  8. Discrete.Differential.Geometry-An.Applied.Introduction(sig2008)笔记

    -------------------------------------------------------------- Chapter 1: Introduction to Discrete D ...

  9. 为什么在ucos向stm32f103移植时说os_cpu_c.c中有三个函数如OS_CPU_SysTickInit()需要注释掉

    我在看os_cpu_c.c代码时对下面这段话困惑了半天总是在百度的帮助下找到了答案 /*  申明几个函数,这里要注意最后三个函数需要注释掉,为什么呢?    OS_CPU_SysTickHandler ...

  10. 新安装loadrunner无法录制脚本的原因之一及解决方案

    eg:IE浏览器 1.新安装的loadrunner录制脚本,一直是加载中的状态: 2.苦思冥想终于找到解决方案: 3.IE浏览器-->设置-->Internet选项 4."安全& ...