• 模板的特化


    模板的特化


    前几篇的文章介绍了模板的使用基础,本篇文章主要介绍一下c++中模板的特化。
    在这里插入图片描述

    非类型模板参数

    先额外介绍个知识点,非类型模板参数。

    模板参数可以是一个类型,也可以是一个常量,如果是常量,那么这个模板参数就叫做非类型模板参数。

    例如STL中的array的实现:

    template<class T,class N>
    class A
    {
        public:
        	typedef size_t iterator;
    		typedef const size_t const_iterator;
    		array()
    		{
    			size = N;
    		}
    
    		T& operator[](const T& idx)
    		{
    			assert(idx < size);
    			return _a[idx];
    		}
    		iterator begin()
    		{
    			return 0;
    		}
    		iterator end()
    		{
    			return size - 1;
    		}
        
        private:
        T arr[N];//固定大小的数组
        size_t size;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    array使用格式:array<类型,数组大小> 对象名;
    array<int,100> arr;
    
    • 1
    • 2

    array 的成员变量中有一个长度固定的数组arr,array 的模板参数中第二个参数就是N就是非类型模板参数,为常量,在类中可以将该非类型模板参数当成常量来使用;但是也有限制,一般都是整型,浮点型、类、对象、字符串等都是不可以用来做非类型模板参数的。(非类型模板参数必须在编译的时候就能确定)

    模板的特化

    • 虽然模板可以实现一些与类型无关的代码,但是有时候会有冲突,得到的结果不是我们想要的

    例如:

    //比较函数 
    template<class T>
    bool greater( T left,T right)
    {
    	return left > right;
    }
    void test()
    {
        Date d1(2002,2,1);
        Date d2(2003,4,9);
        cout<<greater(&d1,&d2)<<endl;
        //用比较函数比较两个日期,虽然可以成功运行,但是因为我们传参的时候传的是指针类型,那么比较的时候	比较的也就是指针的大小了
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    这个时候模板的特化就派上了用场,就是在原来的模板类基础之上,针对特殊类型所进行特殊化的实现方式。

    函数模板的特化

    函数模板特化的规则:

    • 1.必须要有一个基础的函数模板作为前提

    • 2.关键字template后接一个空的<>

    • 3.函数名后跟一对<>,在其中指定需要特化的类型

    • 4.函数形参列表必须要和模板函数参数类型完全相同,如果不同编译器会报错。

    //函数模板的特化
    template<class T>
    bool greater( T left,T right)
    {
    	return left > right;
    }
    
    template<>
    bool greater<Date*>( Date* left, Date* right)
    {
    	return *left > *right;
    }
    
    //一般的函数模板可以不特化 直接给出 类模板一般才特化
    bool greater(Date* left, Date* right)
    {
    	return *left > *right;
    }
    
    //此时调用下面的函数的时候就会走特化后的比较函数了,得到的就是正确的结果了
    void test()
    {
        Date d1(2002,2,1);
        Date d2(2003,4,9);
        cout<<greater(&d1,&d2)<<endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    类模板的特化

    全特化

    • 全特化就是将模板参数列表中所有的参数都确定化

    规则与函数模板基本相同。

    template<class T1,class T2>
    class A
    {
    public:
    	A()
    	{
    		cout << "A" << endl;
    	}
    };
    
    //全特化
    template<>
    class A<int,double>
    {
    public:
    	A()
    	{
    		cout << "A" << endl;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    偏特化

    • 偏特化就是对模板参数进行进一步的条件限制。
    偏特化的两种形式
    1.部分特化
    //以下面的模板为基础模板
    template<class A,class B>
    class Action
    {
        public:
        Action()
        {
            cout<<"Action"<<endl;
        }
        private:
        A _a;
        B _b;
    };
    
    //限制基础模板的第二个模板参数为double类型
    template<class A>
    class Action<A,double>
    {
         public:
        Action()
        {
            cout<<"Action"<<endl;
        }
        private:
        A _a;
        double _b;
    };
    //限制第一个模板参数为int 第二个模板参数为 char
    template<>
    class Action<int,char>
    {
         public:
        Action()
        {
            cout<<"Action"<<endl;
        }
        private:
        int _a;
        char _b;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    2.进一步限制
    • 偏特化不仅仅时指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。
    template<class T1,class T2>
    class A
    {
       public:
    	A()
    	{
    		cout << "A" << endl;
    	}
    }
    
    //进一步限制 限制两个参数为都必须为指针类型
    template<class T1,class T2>
    class A<T1*,T2*>
    {
    public:
    	A()
    	{
    		cout << "A" << endl;
    	}
    };
    //进一步限制第一个参数是指针类型,第二个参数是引用类型
    
    template<class T1,class T2>
    class A<T1*,T2&>
    {
    public:
    	A()
    	{
    		cout << "A" << endl;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
  • 相关阅读:
    Servlet到底是什么(非常透彻)
    Ubuntu工具-2 OBS Studio
    宁波财经学院程序设计补修单链表
    使用kepware配置opcua服务端,并使用UaExpert作为opc客户端进行连接
    【AI学习】LLaMA 系列模型的进化(一)
    NFT 交易市场的后起之秀要如何超越 OpenSea?
    《机器学习》- 第3章 线性模型
    docker启动mysql实例之后,docker ps命令查询不到
    人工智能理论介绍
    运维中心—监控大盘
  • 原文地址:https://blog.csdn.net/xbhinsterest11/article/details/126160896