Appearance
模板
模板是C++泛型编程的核心,允许编写与类型无关的代码。本章将介绍函数模板、类模板和模板的高级用法。
函数模板
cpp
#include <iostream>
#include <string>
using namespace std;
// ============ 基本函数模板 ============
// 定义函数模板
// template<typename T> 或 template<class T>
template<typename T>
T maxValue(T a, T b) {
return (a > b) ? a : b;
}
// 多个模板参数
template<typename T1, typename T2>
auto add(T1 a, T2 b) -> decltype(a + b) {
return a + b;
}
// C++14:自动推导返回类型
template<typename T1, typename T2>
auto multiply(T1 a, T2 b) {
return a * b;
}
// ============ 模板特化 ============
// 针对特定类型的特化版本
template<>
const char* maxValue<const char*>(const char* a, const char* b) {
return (strcmp(a, b) > 0) ? a : b;
}
// ============ 非类型模板参数 ============
template<typename T, int size>
class FixedArray {
private:
T data[size];
public:
int getSize() { return size; }
T& operator[](int index) {
return data[index];
}
};
int main() {
// 隐式实例化(自动推导类型)
cout << "max(10, 20) = " << maxValue(10, 20) << endl;
cout << "max(3.14, 2.71) = " << maxValue(3.14, 2.71) << endl;
cout << "max('a', 'z') = " << maxValue('a', 'z') << endl;
// 显式指定类型
cout << "max<double>(10, 20.5) = " << maxValue<double>(10, 20.5) << endl;
// 多模板参数
cout << "\nadd(10, 20.5) = " << add(10, 20.5) << endl;
cout << "multiply(3, 4.5) = " << multiply(3, 4.5) << endl;
// 非类型模板参数
FixedArray<int, 5> arr;
for (int i = 0; i < arr.getSize(); i++) {
arr[i] = i * 10;
}
cout << "\nFixedArray: ";
for (int i = 0; i < arr.getSize(); i++) {
cout << arr[i] << " ";
}
cout << endl;
return 0;
}类模板
cpp
#include <iostream>
#include <stdexcept>
using namespace std;
// ============ 基本类模板 ============
template<typename T>
class Container {
private:
T* data;
int size;
int capacity;
public:
// 构造函数
Container(int cap = 10) : capacity(cap), size(0) {
data = new T[capacity];
}
// 析构函数
~Container() {
delete[] data;
}
// 添加元素
void add(const T& value) {
if (size >= capacity) {
// 扩容
int newCapacity = capacity * 2;
T* newData = new T[newCapacity];
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
delete[] data;
data = newData;
capacity = newCapacity;
}
data[size++] = value;
}
// 获取元素
T& get(int index) {
if (index < 0 || index >= size) {
throw out_of_range("索引越界");
}
return data[index];
}
// 获取大小
int getSize() const { return size; }
// 下标运算符
T& operator[](int index) {
return get(index);
}
const T& operator[](int index) const {
if (index < 0 || index >= size) {
throw out_of_range("索引越界");
}
return data[index];
}
};
// ============ 类模板特化 ============
// 全特化
template<>
class Container<bool> {
private:
unsigned char* data;
int size;
int capacity;
public:
Container(int cap = 10) : capacity(cap), size(0) {
int bytes = (cap + 7) / 8;
data = new unsigned char[bytes]();
}
~Container() {
delete[] data;
}
void add(bool value) {
int byteIndex = size / 8;
int bitIndex = size % 8;
if (value) {
data[byteIndex] |= (1 << bitIndex);
} else {
data[byteIndex] &= ~(1 << bitIndex);
}
size++;
}
bool get(int index) {
int byteIndex = index / 8;
int bitIndex = index % 8;
return (data[byteIndex] >> bitIndex) & 1;
}
int getSize() const { return size; }
};
int main() {
// 使用类模板
Container<int> intContainer;
intContainer.add(10);
intContainer.add(20);
intContainer.add(30);
cout << "int容器: ";
for (int i = 0; i < intContainer.getSize(); i++) {
cout << intContainer[i] << " ";
}
cout << endl;
// 字符串容器
Container<string> strContainer;
strContainer.add("Hello");
strContainer.add("World");
strContainer.add("C++");
cout << "string容器: ";
for (int i = 0; i < strContainer.getSize(); i++) {
cout << strContainer[i] << " ";
}
cout << endl;
// bool容器(使用特化版本)
Container<bool> boolContainer;
boolContainer.add(true);
boolContainer.add(false);
boolContainer.add(true);
cout << "bool容器: ";
for (int i = 0; i < boolContainer.getSize(); i++) {
cout << boolContainer.get(i) << " ";
}
cout << endl;
return 0;
}模板高级用法
cpp
#include <iostream>
#include <string>
#include <type_traits>
using namespace std;
// ============ 可变参数模板 ============
// 递归终止条件
template<typename T>
void print(T value) {
cout << value << endl;
}
// 可变参数模板
template<typename T, typename... Args>
void print(T first, Args... rest) {
cout << first << " ";
print(rest...); // 递归调用
}
// C++17:折叠表达式
template<typename... Args>
auto sum(Args... args) {
return (args + ...); // 一元右折叠
}
template<typename... Args>
auto product(Args... args) {
return (... * args); // 一元左折叠
}
// ============ 模板元编程 ============
// 编译时计算阶乘
template<int N>
struct Factorial {
static const int value = N * Factorial<N - 1>::value;
};
// 特化:终止条件
template<>
struct Factorial<0> {
static const int value = 1;
};
// 编译时判断类型
template<typename T>
void process(T value) {
if constexpr (is_integral<T>::value) { // C++17
cout << "整数类型: " << value << endl;
} else if constexpr (is_floating_point<T>::value) {
cout << "浮点类型: " << value << endl;
} else if constexpr (is_pointer<T>::value) {
cout << "指针类型: " << *value << endl;
} else {
cout << "其他类型: " << value << endl;
}
}
// ============ SFINAE ============
// 只对有size()方法的类型有效
template<typename T>
auto getSize(const T& container) -> decltype(container.size()) {
return container.size();
}
// 只对数组类型有效
template<typename T, size_t N>
size_t getSize(const T (&)[N]) {
return N;
}
// ============ 完美转发 ============
template<typename T>
void wrapper(T&& arg) {
// forward保持参数的值类别
process(forward<T>(arg));
}
int main() {
// 可变参数模板
cout << "===== 可变参数模板 =====" << endl;
print(1, 2.5, "hello", 'c');
cout << "\nsum(1, 2, 3, 4, 5) = " << sum(1, 2, 3, 4, 5) << endl;
cout << "product(1, 2, 3, 4, 5) = " << product(1, 2, 3, 4, 5) << endl;
// 模板元编程
cout << "\n===== 模板元编程 =====" << endl;
cout << "5! = " << Factorial<5>::value << endl;
cout << "10! = " << Factorial<10>::value << endl;
// 类型判断
cout << "\n===== 类型判断 =====" << endl;
process(42);
process(3.14);
process("hello");
int x = 100;
process(&x);
// SFINAE
cout << "\n===== SFINAE =====" << endl;
int arr[] = {1, 2, 3, 4, 5};
string str = "hello";
cout << "数组大小: " << getSize(arr) << endl;
cout << "字符串大小: " << getSize(str) << endl;
return 0;
}本章小结
本章学习了:
- 函数模板:定义、实例化、特化
- 类模板:定义、成员函数、特化
- 可变参数模板:参数包、折叠表达式
- 模板元编程:编译时计算、类型判断
- SFINAE:替换失败不是错误
- 完美转发:forward保持值类别
下一章,我们将学习STL标准模板库,了解C++标准库的强大功能。
