template之全特化和偏特化

本文详细介绍了C++模板的全特化和偏特化概念,以及它们的区别和实现方式。全特化适用于函数和类,要求模板参数列表为空。而偏特化仅适用于类,它在实例化时确定使用的模板类。文章还讨论了全特化和偏特化的优先级问题,指出无模板函数的优先级最高,然后是全特化/偏特化,最后是普通模板。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

关于讲过traits萃取器的时候探讨到偏特化的概念, 而在那一篇文章也没有具体解释偏特化是什么, 怎么实现, 所以可能在第一次看得时候会很莫名其妙. 所以我将偏特化放在其后讲解, 为不明白的朋友做一个浅析的讲解. 这里我先聊一下全特化再聊偏特化.

全特化

全特化的模板参数列表应该是为空, 函数和类都可以实现全特化.

template<class T>
void fun(T a)
{
	cout << "fun a = " << a << endl;
}

template<>
void fun(int a)
{
	cout << "fun1 a = " << a << endl;
}

int main()
{
	fun(3.3);
	fun(3);

	exit(0);
}

结果如下

在这里插入图片描述

这就是函数全特化, 根据传入的参数让编译器自动推导参数的类型来调用其特殊的函数.

记住:

  1. 函数的全特化不是重载, 不是重载.
  2. 全特化的参数列表要为空, 为空
  3. 第二点成立是因为我们要实现一个相同的模板, 一个相同的模板

同样, 类的全特化也是一样的, 只要满足上面的三点就行了.

偏特化

函数不能偏特化, 类可以偏特化.

偏特化需要在运行实例化的时候才能推导确定使用哪一个模板类. 偏特化也是以template来声明的,需要给出剩余的”模板形参”和必要的”模板实参”.

template<class T>
class Point
{
	public:
		void Print()
		{
			cout << "Point" << endl;
		}
};
template<class T>
class Point<const T>
{
	public:
		void Print()
		{
			cout << "const Point" << endl;
		}
};
int main()
{
	Point<double> b;
	b.Print();
	Point<const int> c;
	c.Print();

	exit(0);
}

以上就实现了一个关于const T的偏特化, 这就很像traits萃取器实现的偏特化了.
在这里插入图片描述

偏特化的重点 :

  1. 函数不能偏特化, 因为函数可以重载, 也就可以实现类型偏特化一样的功, 而类不可以重载.
  2. 偏特化只是针对一些特殊的参数类型.
  3. 偏特化实现了类的"重载".

还有除了可以特化类模板之外, 还可以对类模板中的成员函数和普通静态成员变量进行特化.

优先级

上面全特化和偏特化还有一点没有谈论到, 关于优先级. 现在我们就来看一下

// 这是上面的一个实例
fun(3.3);
fun(3);

fun(3)的函数不是调用template<class T> void fun(T a)而优先调用的是<int>的全特化模板.

同样偏特化的的例子也能证明这一点

Point<double> b;
b.Print();
Point<const int> c;
c.Print();

类优先调用了最合适的模板.

上面就可以归纳为:

  1. 全特化/偏特化, 普通模板(优先级从左到右依次减小)

现在我们再实现一个普通没有模板的fun函数

void fun(int a) {}

如果继续调用fun(3), 你会发现此时没有任何输出. 那是不是没有实现的模板函数和类的实例会优先被调用呢? 确实如此.

以上就可以归纳为 :

  1. 全特化/偏特化, 普通模板(优先级从左到右依次减小)
  2. 无模板函数优先级最高

总结

函数只能全特化, 不能偏特化, 类既可以全特化, 也可以偏特化. 函数不能偏特化但是可以重载, 类不能进行重载.

优先级 : 无模板函数 > 全特化/偏特化 > 普通模板

现在如果重新去看traits萃取器应该就能理解traits编程使用偏特化的意义.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值