zoukankan      html  css  js  c++  java
  • C++泛型编程之函数模板

    泛型语义

      泛型(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 = 2; long b = 3;   myswap(a,b); //ambiguous   cout<<a<<b<<endl;   return 0; }

    函数模板

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

    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 = 1;
        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 0;
    }

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

    特性小结

    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-1);   quickSort(array,low+1,right);   } }

    int main() {   
    int array[10] = {1,3,5,7,2,4,6,8,0,9};   quickSort<int>(array,0,9);   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 1;   else if(a < b)return -1;   else return 0; }


    //实参为两个 char 指针时, 比较的是指针的大小, //而不是指针指向内容的大小, 此时就需要为该函数模板定义一个特化版本, 即特殊处理的版本: template<> int compare < const char * >( const char* &a, const char* &b) {   return strcmp(a,b); }
    int main() {   
    int a = 3; int b = 5;   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 0; }

    关于模板特化的认识

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

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

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

    适用场景

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

  • 相关阅读:
    objective-c 自定义归档
    GitHub---最简单的使用
    objective-c 单例
    objective-c 通知(Notification)
    objective-c 谓词
    objective-c KVO
    objective-c KVC
    objective-c 协议(Protocol)和代理(Delegate)
    Xcode一些方便的快捷键
    objective-c 类目(Category)和延展(Extension)
  • 原文地址:https://www.cnblogs.com/wangkeqin/p/9240608.html
Copyright © 2011-2022 走看看