摘要:本文通过例子介绍了在 C++标准库中广泛使用的模板特化和偏特化,并指出了模板特化和偏特化的定义规则和应用规则。
关键词:模板、特化、偏特化、全特化
1.引言
C++中的模板分为类模板和函数模板,虽然它引进到C++标准中的时间不是很长,但是却得到了广泛的应用,这一点在STL中有着充分的体现。目前,STL在C++社区中得到了广泛的关注、应用和研究。理解和掌握模板是学习、应用和研究以及扩充STL的基础。而STL模板实例中又充斥着大量的模板特化和偏特化。
2.模板的定义
(1) 类模板
定义一个栈的类模板,它可以用来容纳不同的数据类型
说明如下:
template <class T>
class stack {
private:
  list* top;
public:
  stack();
  stack(const stack&);
  ~stack();
  void push(T&);
  T& pop();
  //…
};
上述定义中,template告诉编译器这是一个模板,尖括号中的<class T >指明模板的参数,可以有一个或多个,具体实现时由用户指定,其中template <class T >中的关键字class可以用关键字typename来代替。
类模板的使用除了要在声明时指明模板参数外,其余均与普通的类相同,例如:
stack<int> int_stack;
stack<char> ch_stack;
stack<string> str_stack;
int_stack.push(10);
ch_stack.push(‘z’);
str_stack.push(“c++”);
(2)   函数模板
假设现在要定义一个max函数来返回同一类型(这种类型是允许比较的)两个值的最大者.
template<class T>
T mymax(const T& t1,const T& t2)
{ return t1 < t2 ? t2 : t1; }
template <class T>的意义与类模板定义中相同。
模板函数的使用与普通非模板函数使用相同,因为模板函数的参数可以从其传入参数中解析出来。例如:
int highest = mymax(5,10);
char c = mymax(‘a’, ’z’);
mymax(5,10)解析出模板函数参数为int, mymax(‘a’, ’z’)解析出模板函数的参数为char。
3.模板的特化
(1)   类模板特化
有时为了需要,针对特定的类型,需要对模板进行特化,也就是特殊处理.例如,stack类模板针对bool类型,因为实际上bool类型只需要一个二进制位,就可以对其进行存储,使用一个字或者一个字节都是浪费存储空间的.
template <class T>
class stack {};
template < >
class stack<bool> { //…// };
上述定义中template < >告诉编译器这是一个特化的模板。
(2) 函数模板的特化
看下面的例子
main()
{
  int highest = mymax(5,10);
  char c = mymax(‘a’, ’z’);
  const char* p1 = “hello”;
  const char* p2 = “world”;
  const char* p = mymax(p1,p2);
}
前面两个mymax都能返回正确的结果.而第三个却不能,因为,此时mymax直接比较两个指针p1 和 p2 而不是其指向的内容.
针对这种情况,当mymax函数的参数类型为const char* 时,需要特化。
template <class T>
T mymax(const T t1, const T t2)
{
   return t1 < t2 ? t2 : t1;
}

template <>
const char* mymax(const char* t1,const char* t2)
{
   return (strcmp(t1,t2) < 0) ? t2 : t1;
}
现在mymax(p1,p2)能够返回正确的结果了。
4.模板的偏特化
模板的偏特化是指需要根据模板的某些但不是全部的参数进行特化
(1) 类模板的偏特化
例如c++标准库中的类vector的定义
template <class T, class Allocator>
class vector { // … // };
template <class Allocator>
class vector<bool, Allocator> { //…//};
这个偏特化的例子中,一个参数被绑定到bool类型,而另一个参数仍未绑定需要由用户指定。
(2) 函数模板的偏特化
  严格的来说,函数模板并不支持偏特化,但由于可以对函数进行重载,所以可以达到类似于类模板偏特化的效果。
  template <class T> void f(T);  (a)
  根据重载规则,对(a)进行重载
  template < class T> void f(T*);  (b)
  如果将(a)称为基模板,那么(b)称为对基模板(a)的重载,而非对(a)的偏特化。C++的标准委员会仍在对下一个版本中是否允许函数模板的偏特化进行讨论。
5.模板特化时的匹配规则
(1) 类模板的匹配规则
最优化的优于次特化的,即模板参数最精确匹配的具有最高的优先权
例子:
template <class T> class vector{//…//}; // (a)  普通型
template <class T> class vector<T*>{//…//};  // (b) 对指针类型特化
template <>   class vector <void*>{//…//};  // (c) 对void*进行特化
每个类型都可以用作普通型(a)的参数,但只有指针类型才能用作(b)的参数,而只有void*才能作为(c)的参数
(2) 函数模板的匹配规则
非模板函数具有最高的优先权。如果不存在匹配的非模板函数的话,那么最匹配的和最特化的函数具有高优先权
例子:
template <class T> void f(T);  // (d)
template <class T> void f(int, T, double); // (e)
template <class T> void f(T*);  // (f)
template <> void f<int> (int) ; // (g)
void f(double);  // (h)
bool b;
int i;
double d;
f(b); // 以 T = bool 调用 (d)
f(i,42,d) // 以 T = int 调用(e)
f(&i) ; // 以 T = int* 调用(f)

f(d);  //  调用(g)

//全特化参数的类型和顺序都需要
template <> const char* max_(const char* const &a,const char* const &b)
{
  return strcmp(a,b) >= 0 ? a : b;
}
template <class T,class P> struct A
{
A(const T &a,const P &b)
{
std::cout<<"类模板无特化,"<<"a:"<<a<<",b:"<<b<<endl;
}
};
template <> struct A <const char *,int>
{
A(const char *a,int b)
{
std::cout<<"类模板全特化,"<<"a:"<<a<<",b:"<<b<<endl;
}
};
template <class T> struct A <const T&,int>
{
A(const T& a,int b)
{
std::cout<<"类模板偏特化,"<<"a:"<<a<<",b:"<<b<<endl;
}
};

C++模板偏特化和全特化相关推荐

  1. 模板特化,全特化,偏特化,全部特化,部分特化的含义

    模板特化,任何针对模板参数进一步进行条件限制设计的特化版本.<泛型思维> 全特化就是全部特化,即针对所有的模板参数进行特化.<c++ primer> 偏特化就是部分特化,即针对 ...

  2. (函数/类模板)的(偏特化/全特化)

    特化的概念 特化,就是将泛型的东东搞得"具体化"一些,从字面上来解释,就是为已有的模板参数进行一些使其特殊化的指定,使得以前不受任何约束的模板参数,或受到特定的修饰或完全被指定了下 ...

  3. C/Cpp / STL / 模板全特化和偏特化

    栗子 #include <iostream>template <typename T1, typename T2> struct Test {void Print() { st ...

  4. 模板类的全特化、偏特化

    我们先来定义一个普通的模板类 1 template<class T> 2 struct Test 3 { 4 Test(){ cout << "模板类" & ...

  5. [C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)

    http://www.cnblogs.com/alephsoul-alephsoul/archive/2012/10/18/2728753.html 1.  主版本模板类 首先我们来看一段初学者都能看 ...

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

    模板为什么要特化,因为编译器认为,对于特定的类型,如果你能对某一功能更好的实现,那么就该听你的. 模板分为类模板与函数模板,特化分为全特化与偏特化.全特化就是限定死模板实现的具体类型,偏特化就是如果这 ...

  7. Th4.6:模板全特化、偏特化(局部特化)详述

    本小节回顾的知识点分别是模板全特化.偏特化(局部特化). 今天总结的知识分为以下4个大点: (1)特化与泛化 (2)类模板特化     (2.1)类模板全特化         a)常规全特化      ...

  8. 模板 泛化 全特化 偏特化

    template<>出现,就表示要特化了 为什么要特化呢?泛化不就是为了解决数据类型不一致吗? 泛化是通用,特化是优化,缺一不可 特化,又被成为全特化 full-specializatio ...

  9. C++ 模板偏特化-来自STL的思考

    之前学习STL时接触过一段时间的模板,模板是C++泛型编程编程的基础 STL从头到尾都是模板泛型编程,我觉得用的最巧妙的就是在traits萃取技巧时用到的模板偏特化 先简要回顾一下模板吧,模板主要分为 ...

  10. 【C++ Primer | 16】容器适配器全特化、偏特化

    上面对模板的特化进行了总结.那模板的偏特化呢?所谓的偏特化是指提供另一份模板定义式,而其本身仍为模板:也就是说,针对模板参数更进一步的条件限制所设计出来的一个特化版本.这种偏特化的应用在STL中是随处 ...

最新文章

  1. 没有顶会的CV/NLP方向的博士生毕业出路在哪里?
  2. SAP MM 如何查询物料凭证号是由哪个IDoc Post后产生的?
  3. 集合框架Map、List、Set
  4. iredmail安装roundcube webmail插件
  5. 【机器学习】九种顶流回归算法及实例总结
  6. Spring MVC @ModelAttribute 详解
  7. marc数据个人心得
  8. 获取数组中连续相同的元素
  9. python中的logger模块详细讲解
  10. word文本框跨页显示方法
  11. LINQ之Order By
  12. ABP框架系列之六:(Value-Objects-值对象)
  13. 【报告分享】2019年度薪酬白皮书.pdf(附下载链接)
  14. 阿里云仓库使用小技巧
  15. 高斯函数、高斯积分和正态分布
  16. 美通社:2018年全球企业品牌影响力调查报告
  17. vue中路由跳转怎样刷新页面保证页面更新
  18. 怎么解决运行时输入错误,请重新输入以及专业无法输入的问题
  19. vue.js 的学习之路
  20. 独立博客怎样申请谷歌Adsense

热门文章

  1. unity3d 中添加视频
  2. 如何使用阿里云进行人脸和身份证头像验证比对(人证核验接口API)--java
  3. windows 2012下安装.NET框架时出现组件的文件跟组件清单中的验证信息不匹配,无法安装
  4. jquery 立体走马灯_jquery实现跑马灯效果(一)
  5. 微信小程序打开位置有偏差的解决方案
  6. 基于C++的psf2otf实现
  7. selenium+chromedriver自动打开谷歌进行搜索
  8. 增强无线路由器信号的方法与技巧
  9. JAVA程序员必看的15本书-JAVA自学书籍推荐(转)
  10. 嵌入式车牌识别与称重系统