函数模板为什么没有偏特化?

本文详细解释了C++中的类模板和函数模板的特化与偏特化概念,以及为何函数模板没有偏特化。通过实例展示了模板匹配的过程,包括非模板函数和不同模板函数的选择优先级。

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

C++中有类模板和函数模板,类模板有特化和偏特化两种形式,而函数模板只有特化,没有偏特化,这是因为函数重载的原因,普通函数有函数重载,函数模板也有重载的概念,下面举一个例子来详细说明。

#include <iostream>
using namespace std;
// 1. first template with 2 parameters
template <typename A, typename B>
void f(A a, B b)
{
	std::cout << "template with 2 parameters" << std::endl;
}
// 2. specifized of 2 parameters
template <>
void f<int, int>(int a, int b)
{
	std::cout << "Specialized of 2 parameters" << std::endl;
}
// 3. so called partial specialized
template <typename A>
void f<A, int>(A a, int b)
{
	std::cout << "so called partial Specialized of 1 parameters" << std::endl;
}
// 4. second template
// template <typename A>
// void f(A a, int b) {
//     std::cout << "template with only 1 parameter." << std::endl;
// }
// 5. non-template function
// void f(int a, int b)
// {
// 	std::cout << "non-template function" << std::endl;
// }
int main()
{
	int a = 10;
	double b = 12;
	f(a, b);
	f(a, a);
}

上面的代码我们定义了一个带有两个参数的函数模板(1 处),2处进行了特化,3处我们期望的是对其中一个参数B进行特化,而只保留参数A,可是由于函数模板可以进行重载,编译器把

template <typename A> void f<A, int>(A a, int b){} 当成一个新的函数模板,这个函数模板只有一个形参,而函数本身使用两个参数,其中一个是行参A,另一个是一个int参数,于是上述的代码就不符合函数模板的语法,因为f<A,int>的形式不合法,因此编译不过去,所以我们期望的函数模板偏特化就非法了,改为4处的代码就可以编译通过了。

下面看一下编译器如何选择在非模板函数,不同函数模板之间如何选择的问题:

#include <iostream>
using namespace std;
// 1. first template with 2 parameters
template <typename A, typename B>
void f(A a, B b)
{
	std::cout << "template with 2 parameters" << std::endl;
}
// 2. specifized of 2 parameters
template <>
void f<int, int>(int a, int b)
{
	std::cout << "Specialized of 2 parameters" << std::endl;
}
// 3. so called partial specialized
// template <typename A>
// void f<A, int>(A a, int b)
// {
// 	std::cout << "so called partial Specialized of 1 parameters" << std::endl;
// }
// 4. second template
template <typename A>
void f(A a, int b) {
    std::cout << "template with only 1 parameter." << std::endl;
}
// 5. non-template function
void f(int a, int b)
{
	std::cout << "non-template function" << std::endl;
}
int main()
{
	int a = 10;
	double b = 12;
	f(a, b);
	f(a, a);
}

运行结果如下:

1. 优先选择非模板函数(5处),f(a,a)使用函数5处.

如果把5处的函数禁用,获得结果如下,f(a,a)使用4处的模板特例化,而不是采用2处的两个参数的特化版本:

2. 使用函数模板的时候,从最少行参的模板开始匹配,上述例子中模板4处只有一个行参,而且可以匹配f(a,a),于是编译器就根据这个模板形成f(int,int)的函数。而2处的

template <> void f<int, int>(int a, int b)由于是两个行参的函数模板的特化,所以优先级没有一个行参的函数模板高,因此永远没有机会被采用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值