By SmartPtr(http://www.cppblog.com/SmartPtr/)

模板特化不同于模板的实例化,模板参数在某种特定类型下的具体实现称为模板的特化,以实现特定类型下非通用行为。模板特化有时也称之为模板的具体化,分别有函数模板特化和类模板特化。

针对一个模板参数的类模板特化的几种类型, 一是特化为绝对类型(全特化); 二是特化为引用,指针类型(半特化、偏特化);三是特化为另外一个类模板(复杂点的偏特化)。
用一个简单的例子来说明这三种:

  1. // general version
  2. template<class T>
  3. class Compare
  4. {
  5. public:
  6. static bool IsEqual(const T& lh, const T& rh)
  7. {
  8. return lh == rh;
  9. }
  10. };

这是一个用于比较的类模板,里面可以有多种用于比较的函数, 以IsEqual为例。
一、特化为绝对类型
也就是说直接为某个特定类型做特化,这是我们最常见的一种特化方式,
如特化为float, double等

  1. // specialize for float
  2. template<>
  3. class Compare<float>
  4. {
  5. public:
  6. static bool IsEqual(const float& lh, const float& rh)
  7. {
  8. return abs(lh - rh) < 10e-;
  9. }
  10. };
  11.  
  12. // specialize for double
  13. template<>
  14. class Compare<double>
  15. {
  16. public:
  17. static bool IsEqual(const double& lh, const double& rh)
  18. {
  19. return abs(lh - rh) < 10e-;
  20. }
  21. };

二、特化为引用,指针类型
这种特化我最初是在stl源码的的iterator_traits特化中发现的, 如下:

  1. template <class _Iterator>
  2. struct iterator_traits {
  3. typedef typename _Iterator::iterator_category iterator_category;
  4. typedef typename _Iterator::value_type value_type;
  5. typedef typename _Iterator::difference_type difference_type;
  6. typedef typename _Iterator::pointer pointer;
  7. typedef typename _Iterator::reference reference;
  8. };
  9.  
  10. // specialize for _Tp*
  11. template <class _Tp>
  12. struct iterator_traits<_Tp*> {
  13. typedef random_access_iterator_tag iterator_category;
  14. typedef _Tp value_type;
  15. typedef ptrdiff_t difference_type;
  16. typedef _Tp* pointer;
  17. typedef _Tp& reference;
  18. };
  19.  
  20. // specialize for const _Tp*
  21. template <class _Tp>
  22. struct iterator_traits<const _Tp*> {
  23. typedef random_access_iterator_tag iterator_category;
  24. typedef _Tp value_type;
  25. typedef ptrdiff_t difference_type;
  26. typedef const _Tp* pointer;
  27. typedef const _Tp& reference;
  28. };

当然,除了T*, 我们也可以将T特化为 const T*, T&, const T&等,以下还是以T*为例:

  1. // specialize for T*
  2. template<class T>
  3. class Compare<T*>
  4. {
  5. public:
  6. static bool IsEqual(const T* lh, const T* rh)
  7. {
  8. return Compare<T>::IsEqual(*lh, *rh);
  9. }
  10. };

这种特化其实是就不是一种绝对的特化, 它只是对类型做了某些限定,但仍然保留了其一定的模板性,这种特化给我们提供了极大的方便, 如这里, 我们就不需要对int*, float*, double*等等类型分别做特化了。

三、特化为另外一个类模板

这其实是第二种方式的扩展,其实也是对类型做了某种限定,而不是绝对化为某个具体类型,如下:

  1. // specialize for vector<T>
  2. template<class T>
  3. class Compare<vector<T> >
  4. {
  5. public:
  6. static bool IsEqual(const vector<T>& lh, const vector<T>& rh)
  7. {
  8. if(lh.size() != rh.size()) return false;
  9. else
  10. {
  11. for(int i = ; i < lh.size(); ++i)
  12. {
  13. if(lh[i] != rh[i]) return false;
  14. }
  15. }
  16. return true;
  17. }
  18. };

这就把IsEqual的参数限定为一种vector类型, 但具体是vector<int>还是vector<float>, 我们可以不关心, 因为对于这两种类型,我们的处理方式是一样的,我们可以把这种方式称为“半特化”。

当然, 我们可以将其“半特化”为任何我们自定义的模板类类型:

  1. // specialize for any template class type
  2. template <class T1>
  3. struct SpecializedType
  4. {
  5. T1 x1;
  6. T1 x2;
  7. };
  8. template <class T>
  9. class Compare<SpecializedType<T> >
  10. {
  11. public:
  12. static bool IsEqual(const SpecializedType<T>& lh, const SpecializedType<T>& rh)
  13. {
  14. return Compare<T>::IsEqual(lh.x1 + lh.x2, rh.x1 + rh.x2);
  15. }
  16. };

这就是三种类型的模板特化, 我们可以这么使用这个Compare类:

  1. // int
  2. int i1 = ;
  3. int i2 = ;
  4. bool r1 = Compare<int>::IsEqual(i1, i2);
  5.  
  6. // float
  7. float f1 = ;
  8. float f2 = ;
  9. bool r2 = Compare<float>::IsEqual(f1, f2);
  10.  
  11. // double
  12. double d1 = ;
  13. double d2 = ;
  14. bool r3 = Compare<double>::IsEqual(d1, d2);
  15.  
  16. // pointer
  17. int* p1 = &i1;
  18. int* p2 = &i2;
  19. bool r4 = Compare<int*>::IsEqual(p1, p2);
  20.  
  21. // vector<T>
  22. vector<int> v1;
  23. v1.push_back();
  24. v1.push_back();
  25.  
  26. vector<int> v2;
  27. v2.push_back();
  28. v2.push_back();
  29. bool r5 = Compare<vector<int> >::IsEqual(v1, v2);
  30.  
  31. // custom template class
  32. SpecializedType<float> s1 = {10.1f,10.2f};
  33. SpecializedType<float> s2 = {10.3f,10.0f};
  34. bool r6 = Compare<SpecializedType<float> >::IsEqual(s1, s2);

 

C++模板编程中只特化模板类的一个成员函数(花样特化一个成员函数)的方法

C++函数模板的特化

函数模板的特化,函数模板只有全特化,没有半特化
看下面的例子

  1. main()
  2. {
  3. int highest = mymax(,);
  4. char c = mymax(‘a’, z’);
  5. const char* p1 = hello”;
  6. const char* p2 = world”;
  7. const char* p = mymax(p1,p2);
  8. }

前面两个mymax都能返回正确的结果.而第三个却不能,因为,此时mymax直接比较两个指针p1 和 p2 而不是其指向的内容.
针对这种情况,当mymax函数的参数类型为const char* 时,需要特化。

  1. template <class T>
  2. T mymax(const T t1, const T t2)
  3. {
  4. return t1 < t2 ? t2 : t1;
  5. }
  6. template <>
  7. const char* mymax(const char* t1,const char* t2)
  8. {
  9. return (strcmp(t1,t2) < ) ? t2 : t1;
  10. }

现在mymax(p1,p2)能够返回正确的结果了

函数模板的偏特化

严格的来说,函数模板并不支持偏特化,但由于可以对函数进行重载,所以可以达到类似于类模板偏特化的效果。
template <class T> void f(T); (a)
根据重载规则,对(a)进行重载
template < class T> void f(T*); (b)
如果将(a)称为基模板,那么(b)称为对基模板(a)的重载,而非对(a)的偏特化。

C++的标准委员会仍在对下一个版本中是否允许函数模板的偏特化进行讨论。

C++模板的特化的更多相关文章

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

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

  2. C++—模板(2)类模板与其特化

    我们以顺序表为例来说明,普通顺序表的定义如下: typedef int DataType; //typedef char DataType; class SeqList { private : Dat ...

  3. C++中模板的特化与偏特化

    1.引言 C++中的模板分为类模板和函数模板,虽然它引进到C++标准中的时间不是很长,但是却得到了广泛的应用,这一点在STL中有着充分的体现.目前,STL在C++社区中得到了广泛的关注.应用和研究.理 ...

  4. [转]C++中模板的特化与偏特化

    转载自:http://hi.baidu.com/klcdyx2008/blog/item/5adbf77b79f316f90bd1873c.html 1.引言C++中的模板分为类模板和函数模板,虽然它 ...

  5. 【校招面试 之 C/C++】第2题 函数模板、类模板、特化、偏特化

    1.C++模板 说到C++模板特化与偏特化,就不得不简要的先说说C++中的模板.我们都知道,强类型的程序设计迫使我们为逻辑结构相同而具体数据类型不同的对象编写模式一致的代码,而无法抽取其中的共性,这样 ...

  6. C++模板的特化与偏特化

    http://cppblog.com/SmartPtr/archive/2007/07/04/27496.html (1) 类模板定义一个栈的类模板,它可以用来容纳不同的数据类型 template & ...

  7. C++ enable_if 模板特化实例(函数返回值特化、函数参数特化、模板参数特化、模板重载)

    1. enable_if 原理 关于 enable_if 原理这里就不细说了,网上有很多,可以参考如下教程,这里只讲解用法实例,涵盖常规使用全部方法. 文章1 文章2 文章3 1. 所需头文件 #in ...

  8. C++ 函数模板“偏特化”

         模板是C++中很重要的一个特性,利用模板可以编写出类型无关的通用代码,极大的减少了代码量,提升工作效率.C++中包含类模板.函数模板,对于需要特殊处理的类型,可以通过特化的方式来实现特定类型 ...

  9. 函数模板“偏特化” (C++)

         模板是C++中很重要的一个特性,利用模板可以编写出类型无关的通用代码,极大的减少了代码量,提升工作效率.C++中包含类模板.函数模板,对于需要特殊处理的类型,可以通过特化的方式来实现特定类型 ...

随机推荐

  1. [简记] github 上的 GraphQL v4 API

    突发奇想,想用github做一个支持rss的blog体系,或者就是知识管理体系,简单看了下,把测试用的暂存起来 # Type queries into this side of the screen, ...

  2. 2018-02-27 "Literate Programming"一书摘记之一

    书到后才发现是Knuth的论文集, 第一篇就在网上: Computer programming as an art (1974). 其中"Taste and Style"(品味和风 ...

  3. Hbase简单配置与使用

    一. HBase的 二.基于Hadoop的HBase架构 HBase内置有zookeeper,但一般我们会有其他的Zookeeper集群来监管master和regionserver,Zookeeper ...

  4. 纯小白入手 vue3.0 CLI - 3.3 - 路由的导航守卫

    vue3.0 CLI 真小白一步一步入手全教程系列:https://www.cnblogs.com/ndos/category/1295752.html 尽量把纷繁的知识,肢解重组成为可以堆砌的知识. ...

  5. Apex计划作业框架的实现

    Apex计划作业框架的实现 在本文中,我们实现一个简单的"计划作业框架",用于实现数据的定时自动处理. Apex相关接口 Apex中提供了一组接口用来实现数据的处理.我们主要使用以 ...

  6. Loading加载页面

    一般页面有四种情况 加载中 :就是滚动页面,后台获取加载的数据,每个页面的数据不同所以就让子类来实现,直接抽象abstract了. 加载失败 :一般都需要点击后重新加载 空页面 :也需要点击后重新加载 ...

  7. 安卓APP应用在各大应用市场上架方法整理

    想要把APP上架到应用市场都要先注册开发者账号才可以.这里的方法包括注册帐号和后期上架及一些需要注意的问题.注意:首次提交应用绝对不能随便删除,否则后面再提交会显示应用APP冲突,会要求走应用认领流程 ...

  8. Asp.net Mvc、webApi配置允许跨域

    Web.config 下<system.webServer> 节点下配置 <httpProtocol> <customHeaders> <add name=& ...

  9. Pandas:让你像写SQL一样做数据分析

    1. 引言 Pandas是一个开源的Python数据分析库.Pandas把结构化数据分为了三类: Series,1维序列,可视作为没有column名的.只有一个column的DataFrame: Da ...

  10. 【PAT】B1001 害死人不偿命的(3n+1)猜想

    超级简单题 偶数砍掉一半, 奇数乘三加一砍掉一半 #include<stdio.h> int mian(){ int n,step=0; scanf("%d",n); ...