C++ 变参模板
外观
C++变参模板(Variadic Templates)[编辑 | 编辑源代码]
变参模板(Variadic Templates)是C++11引入的一项强大特性,允许模板接受任意数量、任意类型的模板参数。它是实现泛型编程和元编程的重要工具,广泛应用于标准库(如`std::tuple`、`std::function`)和现代C++框架中。
基本概念[编辑 | 编辑源代码]
变参模板的核心语法是通过省略号(`...`)声明参数包(Parameter Pack),并在后续展开使用。参数包分为两种:
- 模板参数包(Template Parameter Pack):在模板声明中接受多个参数。
- 函数参数包(Function Parameter Pack):在函数参数列表中接受多个参数。
语法示例[编辑 | 编辑源代码]
// 模板参数包
template<typename... Args>
void foo(Args... args); // 函数参数包
参数包的展开[编辑 | 编辑源代码]
参数包必须通过展开(Expansion)才能使用,常见方式包括:
递归展开[编辑 | 编辑源代码]
通过递归模板函数逐层处理参数包中的每个参数。
// 基准情形(终止递归)
void print() {
std::cout << "End\n";
}
// 递归展开
template<typename T, typename... Args>
void print(T first, Args... args) {
std::cout << first << "\n";
print(args...); // 递归调用
}
int main() {
print(1, 2.5, "Hello");
}
输出:
1 2.5 Hello End
折叠表达式(C++17)[编辑 | 编辑源代码]
简化递归展开的语法,支持一元或二元操作符。
template<typename... Args>
auto sum(Args... args) {
return (args + ...); // 折叠表达式
}
int main() {
std::cout << sum(1, 2, 3, 4); // 输出:10
}
实际应用案例[编辑 | 编辑源代码]
实现泛型日志函数[编辑 | 编辑源代码]
template<typename... Args>
void log(const char* format, Args... args) {
printf(format, args...);
}
int main() {
log("Value: %d, Name: %s\n", 42, "Alice");
}
构建元组(std::tuple)[编辑 | 编辑源代码]
变参模板是`std::tuple`的实现基础:
template<typename... Types>
class Tuple;
// 特化递归定义
template<typename Head, typename... Tail>
class Tuple<Head, Tail...> : private Tuple<Tail...> {
Head value;
};
template<>
class Tuple<> {}; // 基准情形
高级主题[编辑 | 编辑源代码]
参数包的大小[编辑 | 编辑源代码]
使用`sizeof...(Args)`获取参数包中参数的数量:
template<typename... Args>
void countArgs(Args... args) {
std::cout << sizeof...(Args) << "\n";
}
完美转发参数包[编辑 | 编辑源代码]
结合`std::forward`实现完美转发:
template<typename... Args>
void wrapper(Args&&... args) {
some_function(std::forward<Args>(args)...);
}
总结[编辑 | 编辑源代码]
- 变参模板通过参数包和展开机制支持任意数量和类型的参数。
- 递归展开是基础方法,折叠表达式(C++17)提供更简洁的语法。
- 广泛应用于标准库、日志系统、元编程等场景。