模板的特化

模板的特化


前几篇的文章介绍了模板的使用基础,本篇文章主要介绍一下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;
}
array使用格式:array<类型,数组大小> 对象名;
array<int,100> arr;

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.关键字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;
}

类模板的特化

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

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

template<class T1,class T2>
class A
{
public:
	A()
	{
		cout << "A<T1,T2>" << endl;
	}
};

//全特化
template<>
class A<int,double>
{
public:
	A()
	{
		cout << "A<int,double>" << endl;
	}
};
偏特化
  • 偏特化就是对模板参数进行进一步的条件限制。
偏特化的两种形式
1.部分特化
//以下面的模板为基础模板
template<class A,class B>
class Action
{
    public:
    Action()
    {
        cout<<"Action<A,B>"<<endl;
    }
    private:
    A _a;
    B _b;
};

//限制基础模板的第二个模板参数为double类型
template<class A>
class Action<A,double>
{
     public:
    Action()
    {
        cout<<"Action<A,double>"<<endl;
    }
    private:
    A _a;
    double _b;
};
//限制第一个模板参数为int 第二个模板参数为 char
template<>
class Action<int,char>
{
     public:
    Action()
    {
        cout<<"Action<int,char>"<<endl;
    }
    private:
    int _a;
    char _b;
};

2.进一步限制
  • 偏特化不仅仅时指特化部分参数,而是针对模板参数更进一步的条件限制所设计出来的一个特化版本。
template<class T1,class T2>
class A
{
   public:
	A()
	{
		cout << "A<T1,T2>" << endl;
	}
}

//进一步限制 限制两个参数为都必须为指针类型
template<class T1,class T2>
class A<T1*,T2*>
{
public:
	A()
	{
		cout << "A<T1*,T2*>" << endl;
	}
};
//进一步限制第一个参数是指针类型,第二个参数是引用类型

template<class T1,class T2>
class A<T1*,T2&>
{
public:
	A()
	{
		cout << "A<T1*,T2&>" << endl;
	}
};
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++ 函数模板特化是指为特定的数据类型或者特定的函数参数提供特殊的实现。这样可以在处理某些特殊情况时,使用不同的实现逻辑,以满足特定的需求。 函数模板特化的语法如下: ```cpp template <> return_type function_name<specific_type>(parameters) { // 实现特化的代码 } ``` 其中,`template <>` 表示这是一个函数模板特化版本,`specific_type` 是要特化的数据类型,`function_name` 是要特化的函数名,`parameters` 是函数的参数列表,`return_type` 是函数的返回类型。 举个例子,设我们有一个通用的函数模板用于计算两个数相加: ```cpp template <typename T> T add(T a, T b) { return a + b; } ``` 如果我们想要为 `int` 类型提供一个特化版本,实现乘法运算而不是加法运算,可以这样写: ```cpp template <> int add<int>(int a, int b) { return a * b; } ``` 这样,在使用 `add` 函数模板时,如果参数是 `int` 类型,就会自动选择特化版本进行计算。 需要注意的是,函数模板特化是根据数据类型进行匹配的,而不是根据参数数量或者参数类型进行匹配。因此,在进行函数模板特化时,要确保特化版本与通用版本的参数类型和数量完全一致,否则可能会导致编译错误。 另外,还可以进行部分特化,即只特化其中一部分参数类型。部分特化的语法与完全特化类似,只是在模板参数列表中指定部分参数类型即可。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值