文章目录
特例化:模板本来是一组通用逻辑的实现,但是对于某些特定的参数类型来说,通用的逻辑实现可能不能满足要求,这时就需要针对这些特殊的类型去实现一个特例模板,即模板的特例化。
全部特例化(全特化):必须有一个主模板(泛化版本),且模板参数被全部指定成具体的类型。
部分特例化(偏特化):必须有一个主模板(泛化版本),且模板参数被部分指定成具体的类型。
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 int
比 int
的范围小,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;
}
输出结果如下: