应用背景:

例如有下面的函数模板,它用来获取两个变量中较大的一个:

  1. template<class T> const T& Max(const T& a, const T& b){
  2. return a > b ? a : b;
  3. }

请读者注意a > b这条语句,>能够用来比较 int、float、char 等基本类型数据的大小,但是却不能用来比较结构体变量、对象以及数组的大小,因为我们并没有针对结构体、类和数组重载>

另外,该函数模板虽然可以用于指针,但比较的是地址大小,而不是指针指向的数据,所以也没有现实的意义。

让模板能够针对某种具体的类型使用不同的算法(函数体或类体不同),这在 C++ 中是可以做到的,这种技术称为模板的显示具体化(Explicit Specialization)

一.函数模板的显式具体化

  1. #include <iostream>
  2. #include <string>
  3.  
  4. using namespace std;
  5.  
  6. typedef struct {
  7. string name;
  8. int age;
  9. float score;
  10. } STU;
  11.  
  12. template<typename T>
  13. const T& Max(const T &a, const T &b);
  14.  
  15. template<>
  16. const STU& Max<STU>(const STU &a, const STU &b);
  17.  
  18. ostream & operator<<(ostream &out, const STU &stu);
  19.  
  20. int main() {
  21.  
  22. int a = ;
  23. int b = ;
  24. cout<<Max(a,b)<<endl;
  25.  
  26. STU stu1 = {"Jack",,95.5};
  27. STU stu2 = {"Mike",,90.0};
  28. cout<<Max(stu1,stu2)<<endl;
  29.  
  30. return ;
  31. }
  32.  
  33. template<typename T>
  34. const T& Max(const T &a, const T &b) {
  35. return a > b ? a : b;
  36. }
  37.  
  38. template<>
  39. const STU& Max<STU>(const STU &a, const STU &b) {
  40. return a.score > b.score ? a : b;
  41. }
  42.  
  43. ostream & operator<<(ostream &out, const STU &stu) {
  44. out<<stu.name<<", "<<stu.age<<", "<<stu.score;
  45. return out;
  46. }

运行结果:

Jack,16,95.5

语法格式为:

  1. template<> const STU& Max(const STU& a, const STU& b);

二.类模板显式具体化

  1. #include <iostream>
  2. #include <string>
  3.  
  4. using namespace std;
  5.  
  6. template<typename T1, typename T2>
  7. class Point {
  8. public:
  9. Point(T1 x, T2 y):m_x(x), m_y(y){}
  10. public:
  11. T1 getX() const {return m_x;}
  12. void setX(T1 x) {m_x = x;}
  13. T2 getY() const {return m_y;}
  14. void setY(T2 y) {m_y = y;}
  15. void display() const;
  16. private:
  17. T1 m_x;
  18. T2 m_y;
  19. };
  20.  
  21. // 这里要带上模板头
  22. template<typename T1, typename T2>
  23. void Point<T1,T2>::display() const {
  24. cout<<"x="<<m_x<<", y="<<m_y<<endl;
  25. }
  26.  
  27. // 类模板显式具体化(针对字符串类型的显式具体化)
  28. template<>
  29. class Point<char *, char *> {
  30. public:
  31. Point(char *x, char *y):m_x(x), m_y(y){}
  32. public:
  33. char* getX() const {return m_x;}
  34. void setX(char *x) {m_x = x;}
  35. char *getY() const {return m_y;}
  36. void setY(char *y) {m_y = y;}
  37. void display() const;
  38. private:
  39. char *m_x;
  40. char *m_y;
  41. };
  42.  
  43. // 注意!这里不能带模板头template<>
  44. void Point<char*, char*>::display() const {
  45. cout<<"x="<<m_x<<", y="<<m_y<<endl;
  46. }
  47.  
  48. int main() {
  49.  
  50. (new Point<int,int>(,))->display();
  51. (new Point<int, char*>(,"jack"))->display();
  52. (new Point<char*,char*>("java","android"))->display();
  53.  
  54. return ;
  55. }

运行结果:

x =10, y = 20

x = 20, y = jack

x = java, y = android

需要注意的是:在类模板的具体化中,成员方法的实例化是不能带模板头template<>的。

三.部分显式具体化

  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. // 类模板
  6. template<typename T1, typename T2>
  7. class Point {
  8. public:
  9. Point(T1 x, T2 y):m_x(x), m_y(y){}
  10. public:
  11. T1 getX() const {return m_x;}
  12. void setX(T1 x){m_x = x;}
  13. T2 getY() const {return m_y;}
  14. void setY(T2 y){m_y = y;}
  15. void display() const;
  16.  
  17. private:
  18. T1 m_x;
  19. T2 m_y;
  20. };
  21.  
  22. template<typename T1, typename T2>
  23. void Point<T1,T2>::display() const {
  24. cout<<"x="<<m_x<<", y="<<m_y<<endl;
  25. }
  26.  
  27. template<typename T2>
  28. class Point<char*, T2> {
  29. public:
  30. Point(char *x, T2 y):m_x(x), m_y(y){}
  31. public:
  32. char *getX() const {return m_x;}
  33. void setX(char *x){m_x = x;}
  34. T2 getY() const {return m_y;}
  35. void setY(T2 y){m_y = y;}
  36. void display() const;
  37. private:
  38. char *m_x;
  39. T2 m_y;
  40. };
  41.  
  42. // 部分显式具体化还是需要加上模板头
  43. template<typename T2>
  44. void Point<char*,T2>::display() const {
  45. cout<<"x="<<m_x<<" | y="<<m_y<<endl;
  46. }
  47.  
  48. int main() {
  49.  
  50. (new Point<int,int>(,))->display();
  51. (new Point<char*,int>("jack",))->display();
  52. (new Point<char*,char*>("java","android"))->display();
  53.  
  54. return ;
  55. }

运行结果:

x = 10, y = 20

x = jack | y = 10

x = java | y = android

注意:

部分显式具体化只能用于类模板,不能用于函数模板

C++语言基础(19)-模板的显式具体化的更多相关文章

  1. C++语言基础(18)-模板

    Java中的泛型编程可以极大的提升编程的效率,比如在android中查找一个控件的ID:标准写法为: TextView tv_text = (TextView)findViewById(R.id.tv ...

  2. C++语言基础(20)-模板的非类型参数

    一.在函数模板中使用非类型参数 #include <iostream> using namespace std; template<class T> void Swap(T & ...

  3. Java入门 - 语言基础 - 19.方法

    原文地址:http://www.work100.net/training/java-method.html 更多教程:光束云 - 免费课程 方法 序号 文内章节 视频 1 概述 2 方法的定义 3 方 ...

  4. C语言基础(19)-结构体,联合体,枚举和typedef

    一.结构体 1.1 结构体struct定义及初始化 #include <stdio.h> // 这个头文件在系统目录下 #include <stdlib.h> // 使用了sy ...

  5. day02<Java语言基础+>

    Java语言基础(常量的概述和使用) Java语言基础(进制概述和二,八,十六进制图解) Java语言基础(不同进制数据的表现形式) Java语言基础(任意进制到十进制的转换图解) Java语言基础( ...

  6. 02 java语言基础

    常量:字面值常量(字符串,字符,整数,小数,布尔,null),自定义常量,''这个不是字符常量,""这个是字符串常量 进制: 02.01_Java语言基础(常量的概述和使用) A: ...

  7. C++基础--函数模板

    函数模板是通用的函数描述,其使用泛型来定义函数.其实就是有些操作,如果撇开具体的变量的数据类型,其操作是一样的如果我们将这些操作写成一个模板,在调用不同变量的时候就设定好变量类型就可了,后续的操作基本 ...

  8. 并发编程 19—— 显式的Conditon 对象

    Java并发编程实践 目录 并发编程 01—— ThreadLocal 并发编程 02—— ConcurrentHashMap 并发编程 03—— 阻塞队列和生产者-消费者模式 并发编程 04—— 闭 ...

  9. C++学习笔记36 (模板的细节明确template specialization)和显式实例(template instantiation)

    C++有时模板很可能无法处理某些类型的. 例如: #include <iostream> using namespace std; class man{ private: string n ...

随机推荐

  1. mysql 获取当前日期及格式化(转)

    MySQL 获取当前日期及日期格式 获取系统日期: NOW() 格式化日期: DATE_FORMAT(date, format) 注: date:时间字段,format:日期格式 select now ...

  2. 【二分法】【尺取法】bzoj2348 [Baltic 2011]Plagiarism

    一开始以为死于精度……调了半天发现死于long long…… 一.二分法: #include<cstdio> #include<cstring> #include<alg ...

  3. 【进制转换】codevs 1474 十进制转m进制

    #include<cstdio> using namespace std; ],en; int main() { scanf("%d%d",&n,&m) ...

  4. 【左偏树】BZOJ2809-[APIO2012]dispatching

    [题目大意] 在一个忍者的帮派里,一些忍者们被选中派遣给顾客,然后依据自己的工作获取报偿.在这个帮派里,有一名忍者被称之为 Master.除了 Master以外,每名忍者都有且仅有一个上级.为保密,同 ...

  5. 1.1(Mybatis学习笔记)初识Mybatis

    一.Mybatis下载与使用 下载地址:https://github.com/mybatis/mybatis-3/releases 下载后解压目录: 需要将lib下的jar包和mybatid-x-x- ...

  6. @RequestParam注解的使用

    自SpringMVC4.2之后,RequestParam内部有4个参数: 1.String name; 2.String value; 3.boolean required; 4.String def ...

  7. Problem A: 零起点学算法16——鸡兔同笼

    #include<stdio.h> int main() { int n,m,a,b; while(scanf("%d %d",&n,&m)!=EOF) ...

  8. BUG:Yii登录时 101 net::ERR_CONNECTION_RESET

    Bug描述:YII web入口登录,无法登录一直等待,最终重定向 原因:设置的默认路由DefauRoute中的控制器中有错误,导致无法跳转找指定的路由规则 解决方案:这就多亏了SourceTree了, ...

  9. 网络采集软件核心技术剖析系列(3)---如何使用C#语言下载博文中的全部图片到本地并可以离线浏览

    一 本系列随笔概览及产生的背景 本系列开篇受到大家的热烈欢迎,这对博主是莫大的鼓励,此为本系列第三篇,希望大家继续支持,为我继续写作提供动力. 自己开发的豆约翰博客备份专家软件工具问世3年多以来,深受 ...

  10. RequireJs 入门

    官网:http://www.requirejs.cn/ 使用方法: 1.引入require.js 可以在底部引入: <script type="text/javascript" ...