1、模板 + 全特化
模板,代表了一种泛化的语义。显然,既然有泛化语义,就应当有特化语义。特化,使得我们能为某些特定的类型专门提供一份特殊实现,以达到某些目的。特化分为全特化与偏特化。所谓全特化,即一个“披着空空如也的template <>的普通函数或类”
#include <iostream>
#include <iomanip>
#include <string>
#include <random>
#include <chrono>
#include <any>
// 标准函数模板
template <typename T>
void Plus(T lv, T rv) {
std::cout << (lv + rv) << "\n";
}
// 全特化版本:当 T 为 int 时,将优先使用此定义
template <>
void Plus(int lv, int rv) {
std::cout << (lv * rv) << "\n";
}
int main() {
Plus(1., 2.); // 使用泛型版本,输出结果 3
Plus(1, 2); // 使用特化版本,输出结果 2
}
2、模板 + 偏特化
偏特化又是什么呢?除了全特化以外的特化,都称为偏特化。从写法上来看,template关键词之后的“<>”不能为空,否则就是全特化。
#include <iostream>
#include <iomanip>
#include <string>
#include <random>
#include <chrono>
#include <any>
// 泛化版本
template <typename T, typename U>
class Entity {
public:
void Add(T lv, U lr) {
std::cout << (lv + lr) << "\n";
}
};
// 偏特化版本1:仅当两个类型一样的时候,才会且一定会使用此版本
template <typename T>
class Entity <T, T> {
public:
void Add(T lv, T lr) {
std::cout << (lv + lr) << "\n";
}
};
// 偏特化版本2:仅当两个类型都是指针的时候,才会且一定会使用此版本
template <typename T, typename U>
class Entity <T*, U*> {
public:
void Add(T* plv, U* prv) {
std::cout << (*plv + *prv) << "\n";
}
};
int main() {
Entity<int, int>().Add(1, 2); // 输出结果 3
Entity<int, long>().Add(2, 3.0); // 输出结果 5
int a = 10;
long b = 20;
Entity<int*, long*>().Add(&a, &b); // 输出结果 30
}
函数模板不是函数,而是一个可以生成函数的语法组分;同理,类模板也不是类,而是一个可以生成类的语法组分。我们称通过函数模板生成函数,或通过类模板生成类的过程为模板实例化。