【深入理解C++】函数模板和类模板的特例化

本文详细介绍了函数模板和类模板的特例化方法,包括全特化和偏特化的应用场景及实现方式。通过实例展示了如何为特定类型提供定制化的模板实现。

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

特例化:模板本来是一组通用逻辑的实现,但是对于某些特定的参数类型来说,通用的逻辑实现可能不能满足要求,这时就需要针对这些特殊的类型去实现一个特例模板,即模板的特例化。

全部特例化(全特化):必须有一个主模板(泛化版本),且模板参数被全部指定成具体的类型。

部分特例化(偏特化):必须有一个主模板(泛化版本),且模板参数被部分指定成具体的类型。

1.函数模板的特例化

1.1 函数模板的全特化

函数模板的全特化等价于函数模板针对特定类型的一个实例化,并不等价于一个函数重载,不能将函数模板的全特化与函数重载混为一谈。

  • 如果使用普通重载函数,那么不管是否发生实际的函数调用,都会在目标文件中生成该函数的二进制代码。
  • 如果使用函数模板的全特化版本,除非发生函数调用,否则不会在目标文件中包含全特化模板函数的二进制代码,这符合函数模板的“惰性实例化”准则。

如下代码所示,对于某些类型(例如字符串类型)来说,编译器默认实例化出来的模板代码的处理逻辑是错误的,此时,我们可以为其提供特例化版本。

#include <iostream>
#include <cstring>
using namespace std;

// Greater是一个函数模板
template <typename T>
bool Greater(T a, T b)
{
	cout << "Greater<T>(T a, T b)" << endl;
	return a > b;
}

// 针对Greater函数模板,提供const char*类型的特例化版本
template <>
bool Greater<const char*>(const char* a, const char* b)
{
	cout << "Greater<const char*>(const char* a, const char* b)" << endl;
	return strcmp(a, b) > 0;
}

int main()
{
	cout << Greater("hello", "world") << endl;
	return 0;
}

在这里插入图片描述

1.2 函数模板不能偏特化

由于函数重载特性的存在,函数模板只能全特化,不能偏特化。

1.3 函数模板、函数模板的全特化、普通函数

调用优先级:普通函数 > 函数模板的全特化 > 函数模板。

#include <iostream>
#include <cstring>
using namespace std;

// Greater是一个函数模板
template <typename T>
bool Greater(T a, T b)
{
	cout << "Greater<T>(T a, T b)" << endl;
	return a > b;
}

// 针对Greater函数模板,提供const char*类型的特例化版本
template <>
bool Greater<const char*>(const char* a, const char* b)
{
	cout << "Greater<const char*>(const char* a, const char* b)" << endl;
	return strcmp(a, b) > 0;
}

// 普通函数
bool Greater(const char* a, const char* b)
{
	cout << "Greater(const char* a, const char* b)" << endl;
	return strcmp(a, b) > 0;
}

int main()
{
	cout << Greater("hello", "world") << endl;
	return 0;
}

在这里插入图片描述

2.类模板的特例化

2.1 类模板的全特化

#include <iostream>
using namespace std;

template <typename T, typename U>
class A    // 主模板
{
public:
	A() { cout << "A<T, U>::A()" << endl; }
	void fun() { cout << "A<T, U>::fun()" << endl; }
};

template <>
class A<int, int>    // 类模板的全特化
{
public:
	A() { cout << "A<int, int>::A()" << endl; }
	void fun() { cout << "A<int, int>::fun()" << endl; }
};

template <>
class A<int, char>    // 类模板的全特化
{
public:
	A() { cout << "A<int, char>::A()" << endl; }
	void fun() { cout << "A<int, char>::fun()" << endl; }
};

int main()
{
	A<int, int> aii;
	aii.fun();

	A<int, char> aic;
	aic.fun();

	A<int, double> aid;
	aid.fun();

	return 0;
}

输出结果如下:

在这里插入图片描述

2.2 类模板成员函数的全特化

#include <iostream>
using namespace std;

template <typename T, typename U>
class A    // 主模板
{
public:
	A() { cout << "A<T, U>::A()" << endl; }
	void fun() { cout << "A<T, U>::fun()" << endl; }
};

template <>
class A<int, int>    // 类模板的全特化
{
public:
	A() { cout << "A<int, int>::A()" << endl; }
	void fun() { cout << "A<int, int>::fun()" << endl; }
};

template <>
class A<int, char>    // 类模板的全特化
{
public:
	A() { cout << "A<int, char>::A()" << endl; }
	void fun() { cout << "A<int, char>::fun()" << endl; }
};

template <>
void A<int, double>::fun()    // 类模板成员函数的全特化
{
	cout << "A<int, double>::fun()" << endl;
}

int main()
{
	A<int, int> aii;
	aii.fun();

	A<int, char> aic;
	aic.fun();

	A<int, double> aid;
	aid.fun();

	return 0;
}

输出结果如下:

在这里插入图片描述

2.3 类模板的偏特化

2.3.1 根据模板参数数量进行偏特化

#include <iostream>
using namespace std;

template <typename T, typename U, typename W>
class A    // 主模板
{
public:
	A() { cout << "A<T, U, W>::A()" << endl; }
	void fun() { cout << "A<T, U, W>::fun()" << endl; }
};

template <typename U>
class A<int, U, double>    // 类模板根据模板参数数量进行偏特化
{
public:
	A() { cout << "A<int, U, double>::A()" << endl; }
	void fun() { cout << "A<int, U, double>::fun()" << endl; }
};

int main()
{
	A<int, int, int> aiii;
	aiii.fun();

	A<int, char, double> aicd;
	aicd.fun();

	return 0;
}

输出结果如下:

在这里插入图片描述

2.3.2 根据模板参数范围进行偏特化

从直观上理解,const intint 的范围小,T*T 的范围小,T&T 的范围小,T&&T 的范围小。

#include <iostream>
using namespace std;

template <typename T>
class A    // 主模板
{
public:
	A() { cout << "A<T>::A()" << endl; }
	void fun() { cout << "A<T>::fun()" << endl; }
};

template <typename T>
class A<const T>    // 类模板根据模板参数范围进行偏特化
{
public:
	A() { cout << "A<const T>::A()" << endl; }
	void fun() { cout << "A<const T>::fun()" << endl; }
};

template <typename T>
class A<T*>    // 类模板根据模板参数范围进行偏特化
{
public:
	A() { cout << "A<T*>::A()" << endl; }
	void fun() { cout << "A<T*>::fun()" << endl; }
};

template <typename T>
class A<T&>    // 类模板根据模板参数范围进行偏特化
{
public:
	A() { cout << "A<T&>::A()" << endl; }
	void fun() { cout << "A<T&>::fun()" << endl; }
};

template <typename T>
class A<T&&>    // 类模板根据模板参数范围进行偏特化
{
public:
	A() { cout << "A<T&&>::A()" << endl; }
	void fun() { cout << "A<T&&>::fun()" << endl; }
};

int main()
{
	A<int> a1;
	a1.fun();

	A<const double> a2;
	a2.fun();

	A<int*> a3;
	a3.fun();

	A<const int*> a4;
	a4.fun();

	return 0;
}

输出结果如下:

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值