C++ 模板参数包展开方式

C++ 模板参数包展开方式

在 C++ 中,模板参数包(Template Parameter Pack)是 C++11 引入的一个强大特性,允许模板接受可变数量的参数。参数包展开(Parameter Pack Expansion)是将参数包解包为单独元素的过程。以下是主要的参数包展开方式:

1. 基本展开方式

cpp 复制代码
template<typename... Args>
void func(Args... args) {
    // Args... 和 args... 都是参数包展开
    other_func(args...); // 展开为 other_func(arg1, arg2, ..., argN)
}

2. 递归展开

最常见的展开方式是通过递归模板实例化:

cpp 复制代码
// 基本情况
void print() {
    std::cout << std::endl;
}

// 递归情况
template<typename T, typename... Args>
void print(T first, Args... args) {
    std::cout << first << " ";
    print(args...); // 递归展开
}

3. 使用逗号运算符展开

cpp 复制代码
template<typename... Args>
void print_all(Args... args) {
    (void)(std::cout << ... << args); // C++17 折叠表达式
    // 或使用逗号运算符展开
    int dummy[] = { (std::cout << args << " ", 0)... };
    (void)dummy; // 避免未使用变量警告
}

4. 初始化列表展开

cpp 复制代码
template<typename... Args>
std::vector<int> make_vector(Args... args) {
    return std::vector<int>{args...}; // 展开为 {arg1, arg2, ..., argN}
}

5. 折叠表达式 (C++17)

C++17 引入了折叠表达式,简化了参数包展开:

cpp 复制代码
template<typename... Args>
auto sum(Args... args) {
    return (args + ...); // 展开为 arg1 + arg2 + ... + argN
}

template<typename... Args>
void print(Args... args) {
    (std::cout << ... << args); // 展开为 std::cout << arg1 << arg2 << ... << argN
}

6. 模板参数展开

cpp 复制代码
template<typename... Args>
struct Tuple {
    std::tuple<Args...> data; // 展开为 std::tuple<Arg1, Arg2, ..., ArgN>
};

7. 完美转发展开

cpp 复制代码
template<typename... Args>
void wrapper(Args&&... args) {
    target_func(std::forward<Args>(args)...); // 完美转发展开
}

8. 模式展开

可以在更复杂的模式中展开参数包:

cpp 复制代码
template<typename... Args>
void foo(Args... args) {
    bar(&args...); // 展开为 bar(&arg1, &arg2, ..., &argN)
    baz(std::pair<Args, int>(args, 0)...); // 展开为 baz(pair<Arg1, int>(arg1, 0), ...)
}

注意事项

  1. 参数包展开必须有一个上下文(如函数调用、初始化列表等)
  2. 展开的语法是在参数包名后加 ...
  3. 参数包展开是编译时行为,不会产生运行时开销
  4. 在 C++17 之前,递归是处理参数包的主要方式

参数包展开是 C++ 模板元编程和泛型编程的强大工具,使得编写接受任意数量参数的通用代码成为可能。

相关推荐
secondyoung6 分钟前
一文丝滑使用Markdown:从写作、绘图到转换为Word与PPT
开发语言·vscode·编辑器·powerpoint·markdown·visual studio·mermaid
Incredibuild29 分钟前
DevSecOps 集成 CI/CD Pipeline:实用指南
c++·ci/cd·devsecops
雨枪幻。1 小时前
spring boot开发:一些基础知识
开发语言·前端·javascript
爱炸薯条的小朋友2 小时前
C#由Dictionary不正确释放造成的内存泄漏问题与GC代系
开发语言·opencv·c#
m0_480502644 小时前
Rust 登堂 之 函数式编程(三)
开发语言·后端·rust
君鼎4 小时前
More Effective C++ 条款01:仔细区别 pointers 和 references
c++
工藤新一¹5 小时前
C/C++ 数据结构 —— 树(2)
c语言·数据结构·c++·二叉树··c/c++
源远流长jerry5 小时前
STM32之DMA详解
linux·网络·c++·stm32·单片机·嵌入式硬件
是店小二呀5 小时前
【C++】智能指针底层原理:引用计数与资源管理机制
android·java·c++
eqwaak06 小时前
科技信息差(8.26)
大数据·开发语言·人工智能·编辑器