C++之可变参数模板

简介

可变参数模板是模板编程时,模板参数(template parameter)的个数可变的情形,可变模板参数(variadic templates)是C++ 11新增的最强大的特性之一,它对参数进行高度泛化,它能表示0到任意个数、任意类型的参数。

C语言中以宏定义的方式实现可变参数

/*
用宏的方式
*/

#define add_1(a) a
#define add_2(a,b) a + b
#define add_3(a,b,c) a + add_2(b,c)

#define add(...)  PASTE(add_ ,GET_ARG_COUNT(__VA_ARGS__)) (__VA_ARGS__)

C++中的可变参数

…在参数的前面,代表的是定义参数
…在参数的后面,代表的是展开的语义

// ...在参数的前面,代表的是定义参数包
// ...在参数的后面,代表的是展开的语义
template<typename... Args>
void f(Args... args){
    constexpr auto s1 = sizeof...(Args); // 模板参数包
    constexpr auto s2 = sizeof...(args); // 函数参数包
    static_assert(s1 == s2);
}

参数包的遍历

递归遍历

// c++ 11 递归的方式
void print(){ }
template<typename A, typename... Args>
void print(const A& arg, const Args&... args){
    std::cout << arg << std::endl;
    print(args...);
}

C++17 折叠表达式遍历

右折叠: (参数包 二元操作符 … [二元操作符 初始值])
左折叠: ([初始值 二元操作符] … 二元操作符 参数包)

// 利用折叠表达式 + 逗号表达式 遍历
template<typename... Args>
void print(const Args&... args){
    ((std::cout << args << std::endl), ...); // 逗号表达式,使用右折叠
    // (... ,(std::cout << args << std::endl)); //使用的是左折叠
}

这里注意上下两种折叠方式的差别,上面使用的是右折叠表达式,下面采用的式左折叠表达式,在结果上两个的实现效果是完全一样的,但是在编译的时候是完全相反的,结果如下(可以看到展开的表达式中括号的差别):

#ifdef INSIGHTS_USE_TEMPLATE
template<>
void print<int, int, int, int, char[6], char>(const int & __args0, const int & __args1, const int & __args2, const int & __args3, const char (&__args4)[6], const char & __args5)
{
  (std::cout.operator<<(__args0).operator<<(std::endl)) , ((std::cout.operator<<(__args1).operator<<(std::endl)) , ((std::cout.operator<<(__args2).operator<<(std::endl)) , ((std::cout.operator<<(__args3).operator<<(std::endl)) , ((std::operator<<(std::cout, __args4).operator<<(std::endl)) , (std::operator<<(std::cout, __args5).operator<<(std::endl))))));
  (((((std::cout.operator<<(__args0).operator<<(std::endl)) , (std::cout.operator<<(__args1).operator<<(std::endl))) , (std::cout.operator<<(__args2).operator<<(std::endl))) , (std::cout.operator<<(__args3).operator<<(std::endl))) , (std::operator<<(std::cout, __args4).operator<<(std::endl))) , (std::operator<<(std::cout, __args5).operator<<(std::endl));

}
#endif

C++20折叠表达式 + apply + auto

可以用lambda就意味着可以用function和bind来实现更加灵活的调用

template<typename... Args>
void dump(const std::tuple<Args...>& tp){
    std::apply([](const auto&... args){
        ((std::cout << args << std::endl), ...);
    },tp);
}

参数包展开和折叠表达式对比

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

折叠表达式详解

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

强大的RGG

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值