泛型语义

  泛型(Generic Programming),即是指具有在多种数据类型上皆可操作的含意。泛型编
程的代表作品 STL 是一种高效、泛型、可交互操作的软件组件。
  泛型编程最初诞生于 C++中,目的是为了实现 C++的 STL(标准模板库)。其语言支
持机制就是模板(Templates)。
  模板的精神其实很简单:类型参数化(type parameterized),即,类型也是一种参数,
也是一种静多态。 换句话说, 把一个原本特定于某个类型的算法或类当中的类型信息抽掉,
抽出来做成模板参数。

函数模板

引子:重载函数,虽然在一定程度上达到了多类型适应的目的,但是不彻底,且有二义性存在。

#include <iostream>
using namespace std;
void myswap(int & a, int &b)
{
  int t = a;
  a = b;
  b = t;
}
void myswap(double & a, double &b)
{
  double t = a;
  a = b;
  b = t;
} int main()
{
  long a = ; long b = ;
  myswap(a,b); //ambiguous
  cout<<a<<b<<endl;
  return ;
}

函数模板

语法:在一个函数的参数表, 返回类型和函数体中使用参数化的类型。

template<typename/class 类型参数 T1, typename/class 类型参数 T2,...>

特点:结构上与普通函数无异,但是在传入参数和返回值上做了泛化

返回类型 函数模板名(函数参数列表)
{
函数模板定义体
}

案例:(概念比较抽象,请通过案例来观察其特点)

 


decltype +auto(c++11新特性)

多种类型混合模板,详情请阅读本人博文《C++11/14的新特性——更简洁》关于decltype的解析。https://www.cnblogs.com/wangkeqin/p/9285682.html

#include <iostream>

using namespace std;

template<typename R, typename T,typename U>
R add(T a, U b)
{
return a+b;
} template<typename R, typename T,typename U>
auto add2(T a, U b)->decltype(a+b)
{
return a+b;
} int main(int argc, char *argv[])
{
int a = ;
float b = 1.1;
auto ret = add<decltype(a+b),int,float>(a,b);
cout<<ret<<endl;
auto ret2 = add2<decltype(a+b)>(a,b);
cout<<ret2<<endl;
return ;
}

函数模板与普通函数的区别无非就是将函数参数高度抽象化,使其具备处理更多数据类型的能力。

特性小结

1)严格匹配,不存在隐式转化。

2)先实例化,再调用。

3)类型参数可以省略。

4)尺有所长,寸有所短。

原理:

  编译器并不是把函数模板处理成能够处理任意类的函数; 编译器从函数模板通过
具体类型产生不同的函数; 编译器会对函数模板进行两次编译: 在声明的地方对模板
代码本身进行编译, 在调用的地方对参数替换后的代码进行编译。

函数模板的应用——将快速排序算法实现模板化

#include <iostream>
#include <typeinfo>
using namespace std;

template<typename T>
void quickSort(T * array,int left, int right)
{
  if(left<right)
  {
    int low = left; int high = right;
    T pivot = array[low];
    while(low<high)
    {
      while(array[high] >= pivot && high>low )
        high--;
      array[low] = array[high];
      while(array[low] <= pivot&& high>low)
        low++;
      array[high] = array[low];
    }
  array[low] = pivot;
  quickSort(array,left,low-);
  quickSort(array,low+,right);
  }
} int main()
{
  int array[] = {,,,,,,,,,};
  quickSort<int>(array,,);
  for(auto i:array)
  {
    cout<<i<<endl;
  }
}

函数模板的默认参数

  函数模板,在调用时,先实例化为模板函数,然后再调用。当然也可以设置默认类
型的默认值。由于系统强大的自动推导能力,有时默认也没有太大的意义。

template<typename T = int>
void quickSort(T * array,int left, int right)

模板特化

  就是在实例化模板时,对特定类型的实参进行特殊处理,即实例化一个特殊的实例版本。

template<typename T> int compare( T &a, T &b)
template<> int compare < const char * >( const char* &a, const char* &b)

  当以特化定义时的形参使用模板时,将调用特化版本,模板特化分为全特化和偏特
化,函数模板的特化,只能全特化;

  比如我们在比较两个数的大小时:

#include <iostream>
#include <string.h>
using namespace std;
template<typename T> int compare( T &a, T &b)
{
  if(a > b) return ;
  else if(a < b)return -;
  else return ;
}

//实参为两个 char 指针时, 比较的是指针的大小,
//而不是指针指向内容的大小, 此时就需要为该函数模板定义一个特化版本, 即特殊处理的版本:
template<> int compare < const char * >( const char* &a, const char* &b)
{
  return strcmp(a,b);
}
int main()
{
  int a = ; int b = ;
  cout<<compare(a,b)<<endl;
  string str1 = "abc",str2 ="abc";
  cout<<compare(str1,str2)<<endl;
  char * p1 = "abc",*p2= "def";
  cout<<compare(p1,p2)<<endl;
  cout<<compare(p2,p1)<<endl;
  return ;
}

关于模板特化的认识

模板特化的原因:当前函数模板的逻辑或者功能,不能满足特定参数的需求。

模板特化的方式:将需要特化的参数提前”布置“到模板中去,提前预定模板,之后传入需要特化的参数时便可以

优先调用经过该参数特化的模板。

适用场景

  函数模板,只适用于函数的参数个数相同而类型不同,且函数体相同的情况。如果
个数不同,则不能用函数模板。

C++泛型编程之函数模板的更多相关文章

  1. 25.C++- 泛型编程之函数模板(详解)

    本章学习: 1)初探函数模板 2)深入理解函数模板 3)多参函数模板 4)重载函数和函数模板 当我们想写个Swap()交换函数时,通常这样写: void Swap(int& a, int&am ...

  2. C++STL - 函数模板

    模板主要是为了泛型编程,做到与类型无关 模板有函数模板和类模板,本文主要整理的是函数模板 1.函数模板定义 template<typename 类型形参1,typename 类型形参2,...& ...

  3. [Reprint] C++函数模板与类模板实例解析

    这篇文章主要介绍了C++函数模板与类模板,需要的朋友可以参考下   本文针对C++函数模板与类模板进行了较为详尽的实例解析,有助于帮助读者加深对C++函数模板与类模板的理解.具体内容如下: 泛型编程( ...

  4. c++函数模板---3

    原创博客:转载请标明出处:http://www.cnblogs.com/zxouxuewei/ 模板从大体上,可以分为两种:函数模板和类模板.函数模板是算法库的基础,类模板是建立标准库容器和迭代器的基 ...

  5. C++_进阶之函数模板_类模板

     C++_进阶之函数模板_类模板 第一部分 前言 c++提供了函数模板(function template.)所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体制定,用一个虚拟的类型来 ...

  6. C++—模板(1)模板与函数模板

    1.引入 如何编写一个通用加法函数?第一个方法是使用函数重载, 针对每个所需相同行为的不同类型重新实现这个函数.C++的这种编程机制给编程者极大的方便,不需要为功能相似.参数不同的函数选用不同的函数名 ...

  7. C++解析(26):函数模板与类模板

    0.目录 1.函数模板 1.1 函数模板与泛型编程 1.2 多参数函数模板 1.3 函数重载遇上函数模板 2.类模板 2.1 类模板 2.2 多参数类模板与特化 2.3 特化的深度分析 3.小结 1. ...

  8. C++ 函数模板一(函数模板定义)

    //函数模板定义--数据类型做参数 #include<iostream> using namespace std; /* 函数模板声明 1.函数模板定义由模板说明和函数定义组成,并且一个模 ...

  9. Template 基础篇-函数模板(待看

    Template 基础篇-函数模板 Template所代表的泛型编程是C++语言中的重要的组成部分,我将通过几篇blog对这半年以来的学习做一个系统的总结,本文是基础篇的第一部分. Template ...

随机推荐

  1. 怎样使用在线Webapp生成器生成安装包

    在这篇文章中,我们来介绍怎样使用在线(online)的Webapp生成器来生产在Ubuntu手机或模拟器中能够安装的click安装包. Webapp生成器的地址:https://developer.u ...

  2. repeter中应用三元运算符

    应用情景一:根据ID显示名称例如:0代表启动,1:代表关闭例子如下 <td><%#Eval("ID").ToString() == "0" ? ...

  3. c# 编程修改 wince 系统时间

    [StructLayout(LayoutKind.Sequential)] public struct SYSTEMTIME { public ushort wYear; public ushort ...

  4. js怎么限制文本框input只能输入数字

    1.说明 本篇文章介绍怎么使用js限制文本框只能输入数字 2.HTML代码 <!DOCTYPE html> <html xmlns="http://www.w3.org/1 ...

  5. 负载均衡实现,一个域名对应多个IP地址

    负载均衡实现,一个域名对应多个IP地址 - 宏宇 - 博客园 https://www.cnblogs.com/cuihongyu3503319/archive/2012/07/09/2583129.h ...

  6. 超实用的 Nginx 极简教程,覆盖了常用场景(转)

    概述 安装与使用 安装 使用 nginx 配置实战 http 反向代理配置 负载均衡配置 网站有多个 webapp 的配置 https 反向代理配置 静态站点配置 搭建文件服务器 跨域解决方案 参考 ...

  7. BNUOJ 34978 汉诺塔 (概率dp)

    题目分析:对于 i 个盘 , 须要移动多少步,取决于最大的盘子在哪个杆上.在C杆上,则最大的盘不须要移动,由于初始状态一定是满足盘由下到上盘子依次变小的,仅仅须要移动i - 1个盘.假设在A杆上,则首 ...

  8. AndroidContactsTest.java

    以下代码使用ContactManager.apk进行测试 package com.saucelabs.appium; import io.appium.java_client.AppiumDriver ...

  9. Android如何配置init.rc中的开机启动进程(service)【转】

    本文转载自:http://blog.csdn.net/qq_28899635/article/details/56289063 开篇:为什么写这篇文章 先说下我自己的情况,我是个普通的大四学生,之前在 ...

  10. Yii的缓存机制之片段缓存

      一.首先在main.php配置缓存组件 在components里面添加cache项.代码如下: // application components 'components'=>array( ...