### C++模板基础:函数模板与类模板语法详解
C++模板是泛型编程的核心机制,允许开发者编写与类型无关的代码。通过模板,可以避免为不同数据类型重复编写相似逻辑,显著提升代码复用性和可维护性。本文将系统讲解函数模板和类模板的语法规则、使用场景及高级特性,帮助读者掌握这一强大的编程工具。
一、函数模板基础语法
函数模板通过定义通用函数原型,支持在编译时根据调用参数自动生成特定类型的函数实例。
1.1 基本语法结构
template // 或 class T
T max(T a, T b) {
return (a > b) ? a : b;
}
模板声明以`template`关键字开头,后跟模板参数列表。`typename`或`class`关键字用于声明类型参数(二者在此场景下等价)。函数体中使用模板参数`T`作为占位类型。
1.2 模板实例化
调用模板函数时,编译器根据实参类型推导模板参数:
int a = 5, b = 10;
cout
也可显式指定类型:
double x = 3.14, y = 2.71;
cout (x, y); // 显式实例化为 double 版本
1.3 多参数模板
模板可支持多个类型参数:
template
void printPair(T1 first, T2 second) {
cout
1.4 非类型模板参数
模板参数可以是值而非类型:
template
T arraySum(T arr[]) {
T sum = T(); // 默认构造
for (int i = 0; i (nums); // 输出6
}
二、类模板基础语法
类模板允许定义与类型无关的类结构,常见于容器类(如`std::vector`)的实现。
2.1 基本类模板定义
template
class Stack {
private:
vector elements;
public:
void push(const T& element) {
elements.push_back(element);
}
T pop() {
if (elements.empty()) throw out_of_range("Stack empty");
T element = elements.back();
elements.pop_back();
return element;
}
};
2.2 类模板实例化
Stack intStack;
intStack.push(42);
cout strStack;
strStack.push("Hello");
cout
2.3 模板类成员函数定义
成员函数可在类外定义,需重复模板参数:
template
class Box {
public:
T content;
void print();
};
template
void Box::print() {
cout
2.4 模板特化
可为特定类型提供专门实现:
// 全特化
template
class Stack {
// 针对bool类型的优化实现
};
// 偏特化(针对指针类型)
template
class Stack {
// 针对指针类型的实现
};
三、模板高级特性
3.1 默认模板参数
template
class DefaultType {
T value;
public:
DefaultType(T v) : value(v) {}
T getValue() const { return value; }
};
DefaultType dt(10); // 使用int作为默认类型
3.2 可变参数模板(C++11起)
// 打印任意数量和类型的参数
template
void printAll(Args... args) {
((cout
3.3 模板元编程基础
通过模板实现编译期计算:
template
struct Factorial {
static const int value = N * Factorial::value;
};
template
struct Factorial {
static const int value = 1;
};
cout ::value; // 输出120
四、模板使用最佳实践
4.1 头文件与实现分离
类模板成员函数通常需在头文件中实现,或使用显式实例化:
// stack.h
template
class Stack { /*...*/ };
// stack.cpp
template class Stack; // 显式实例化int版本
4.2 模板参数命名约定
常用命名规范:
- `T`:通用类型
- `Iter`:迭代器类型
- `Key`, `Value`:键值对类型
4.3 避免代码膨胀
显式实例化可减少生成的代码量:
// 在.cpp文件中
template class std::vector; // 仅生成bool版本的vector
五、常见问题与解决方案
5.1 模板参数推导失败
问题示例:
template
void process(T& param) {}
const int x = 10;
process(x); // 推导为int&,无法绑定到const int
解决方案:使用`const T&`或通用引用。
5.2 模板依赖名称问题
问题示例:
template
void foo() {
T::innerType* ptr; // 被解析为乘法而非类型声明
}
解决方案:使用`typename`关键字:
template
void foo() {
typename T::innerType* ptr;
}
5.3 模板递归深度限制
编译期递归可能受编译器限制,可通过迭代替代或增加限制:
#pragma GCC diagnostic ignored "-Wtemplate-recursion-depth"
六、现代C++中的模板演进
6.1 C++17的模板改进
- 类模板参数推导(CTAD):
template
struct Pair {
T first;
T second;
};
Pair p{1, 2}; // 自动推导为Pair
6.2 C++20的概念(Concepts)
约束模板参数:
template
concept Integral = std::is_integral_v;
template
T add(T a, T b) { return a + b; } // 仅接受整数类型
6.3 非类型模板参数扩展
C++20允许使用浮点数和类类型作为非类型参数:
struct Point { int x, y; };
template
class Location {};
关键词:C++模板、函数模板、类模板、模板特化、可变参数模板、模板元编程、概念约束、编译期推导
简介:本文全面解析C++模板编程的核心机制,涵盖函数模板与类模板的基础语法、多参数模板、非类型参数、模板特化等关键特性,并深入探讨可变参数模板、模板元编程等高级技术。结合现代C++标准(C++17/C++20)的新特性,如类模板参数推导和概念约束,提供从基础到进阶的完整知识体系,帮助开发者高效利用模板实现泛型编程。