在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. linux下利用GPRS模块发短信、打电话

    一.开发环境     内核版本:linux-3.0    开发板:FL2440(nandflash:K9F1G08 128M)    GPRS模块:SIM900   二.与发短信和拨号相关的 AT 指 ...

  2. DTO对象

    在EF中,EF生成的对象都是代理对象,这些对象看上去是实体类对象,但是其实都是EF封装好的代理类对象.所以调用EF查询得到的代理类对象有继承于实体对象,所以可以用实体类对象来接收返回的代理类对象.EF ...

  3. 如何比较两个SQL数据库的字段差别。

    程序好几个版本了,数据也弄出好好几版本,这下好了,原程序要升级,当然数据库也要升,可是里面已经有了大量的数据了,这时候怎么办.写了个存储过程来解决,一目了然. 因为2005及以上的数据库已经没有表sy ...

  4. asp.net 导入excel文件

    前台页面: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="b2ccarri ...

  5. 本地搭建ubuntu

    1 使用VMware Workstation 安装ubuntu 14 2 进入ubuntu 命令行 ctrl+alt+f2 3 默认root用户是无固定密码的,并且是被锁定的,如果想给root设置一个 ...

  6. 在ASP.NET Web API中使用OData

    http://www.alixixi.com/program/a/2015063094986.shtml 一.什么是ODataOData是一个开放的数据协议(Open Data Protocol)在A ...

  7. [2016.01.22]万峰文本处理专家 v2.1

    <万峰文本处理专家>是一款简单易用,且功能强大的各类文本文件处理软件.1.支持多任务的处理模式,允许一次处理多个任务.2.支持正则表达式替换,替换更加强大:3.支持各类关键字的行处理操作: ...

  8. resizable.js

    (function($){ var boundbar= { html:"<div class=\"boundbar\" style=\"overflow: ...

  9. MyBatis原理分析之三:初始化(配置文件读取和解析)

    1. 准备工作 编写测试代码(具体请参考<Mybatis入门示例>),设置断点,以Debug模式运行,具体代码如下: )ExecutorType:执行类型,ExecutorType主要有三 ...

  10. [转]mysql在windows下支持表名大小写,lower_case_table_names

    windows下mysql默认是不支表名大小写的,也就是表名大小写不敏感.用phpmyadmin创建的驼峰式表名,全部被强制成小写.mysql表名大小写敏感的参数: lower_case_table_ ...