6、c++特性---可变参数模版和折叠表达式

发布于:2025-03-31 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、可变参数模版【c++11】

  • c++11之前,模版template,只能使用固定的参数数量

  • 但是可变模版可以让你拥有多个各种类型的参数

  • 我们把带省略号的参数称为参数包,参数包里面可以包含0到N 个模板参数,而args则是一个函数形参参数包。

  • 模版一如下,使用递归展开

// 递归终止条件
void print() { cout << endl; } 
//🍎 基本语法:typename... Args 表示可变参数包
template<typename T, typename... Args> // Args是类型参数包
void print(T first, Args... rest) {     // rest是值参数包
    cout << first << " ";
    print(rest...); // 递归展开参数包
}

//📌 使用示例
print(1, 3.14, "hello"); // 输出:1 3.14 hello 

  • 模版二如下,使用if constexpr结合sizeof…(args)的方式展开
template<class T,class...U >

void test(T first,U...others){
    cout<<first<<endl;
    if constexpr (sizeof...(others)>0){
        test(others...);
    }
    
}
int main(){
    test(11,22,33,44,55,66);
    //11 22 33 44 55
}
  • 核心特点允许函数/类接受任意数量/类型的参数,是C++11引入的重要特性。

  • 统计参数数量的方式

template<typename... Args>
void countArgs(Args... args) {
    cout << sizeof...(args) << endl; // 关键符sizeof...
}

二、折叠表达式【c++17】

1、了解

  • 一共就4种形式
    在这里插入图片描述
  • 本质作用提供单行表达式展开参数包的能力取代传统的递归展开方式,代码更简洁、性能更好。
    • op是二元操作符
    • args是参数包
    • init是初始值。

折叠表达式支持所有C++中的二元操作符,包括但不限于:(了解一下就行了)
算术运算符:+, -, *, /, %
逻辑运算符:&&, ||
比较运算符:==, !=, <, >, <=, >=
位运算符:&, |, ^, <<, >>

2、左折叠

  • 从第一个元素开始
#include<iostream>
#include<cstdio>
using namespace std;

template <class ...Args>
auto sum(Args...args){
    return (args+...);
}
int main(){
    int s=sum(1,2,3,4,5);
    printf("%d",s);//15=((((1+2)+3)+4)+5)
}

3、右折叠

  • 从最后一个元素开始
template <class ...Args>
auto sum(Args...args){
    return (...+args);
}
int main(){
    int s=sum(1,2,3,4,5);
    printf("%d",s);//15=(1+(2+(3+(4+5))))
}

4、左折叠带初始

  • 操作开始时,有个初始值
template <typename T,class ...Args>
auto sum(T init,Args...args){
    int s= ((init)+...+args);
    return s;
}
int main(){
    int s=sum((1*10),1,2,3,4,5);
    printf("%d",s);//25
}

5、右折叠带初始

  • 操作结束时,有个初始值
template <typename T,class ...Args>
auto sum(T init,Args...args){
    int s= (args+...+(init));
    return s;
}
int main(){
    int s=sum((1*10),1,2,3,4,5);
    printf("%d",s);//25
}

6、注意

  • 带初始的折叠,左右2边 op 符号要一致
  • 可以使用 sizeof …(args)获取 参数数量
  • init 里有 op符号的话,要把它们括起来 比如 init 是 1 * 2,就要写成 (args +…+(1 * 2))