avatar

我可是会飞的啊

找对象ing

  • 首页
  • ctfs
  • 关于
  • 文件库
  • 留言板
  • 标签
  • 归档
  • 【网课推荐】(红队&二进制)
首页 C++折叠表达式

C++折叠表达式

Posted 2022年 04月 10日 Updated 2023年 03月 1日
By selph
10~13 min read

觉得自己还是需要好好去学一门编程语言,嗯,就C++吧

折叠表达式简介

C++11提供了可变模板参数包,使函数可以接受任意数量的参数。但在C++11中展开参数包稍显麻烦,而 C++17 的折叠表达式使得展开参数包变得容易, 其基本语法是使用 (…) 的语法形式进行展开。

折叠表达式支持的操作符:

+, -, *, /, %, ^, &, |, =, <,
>, <<, >>, +=, -=, *=, /=, %=, ^=, &=, |=, <<=,
>>=,==, !=, <=, >=, &&, ||, ,, .*, ->*.

一元折叠示例

折叠分类:左折叠和右折叠

// 右折叠
template<typename ... T>
auto sum_right(T ... t) {
    return (t + ...);
}

// 左折叠
template<typename ... T>
auto sum_left(T ...t) {
    return (... + t);
}

int main()
{
    std::cout << sum_left(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << std::endl;
    return 0;
}

左折叠反汇编:

00007FF6F44749BC 8B 85 E8 00 00 00    mov         eax,dword ptr [<t_1>] 
00007FF6F44749C2 8B 8D E0 00 00 00    mov         ecx,dword ptr [<t_0>] 
00007FF6F44749C8 03 C8                add         ecx,eax  
00007FF6F44749CA 8B C1                mov         eax,ecx  
00007FF6F44749CC 03 85 F0 00 00 00    add         eax,dword ptr [<t_2>] 
00007FF6F44749D2 03 85 F8 00 00 00    add         eax,dword ptr [<t_3>] 
00007FF6F44749D8 03 85 00 01 00 00    add         eax,dword ptr [<t_4>] 
00007FF6F44749DE 03 85 08 01 00 00    add         eax,dword ptr [<t_5>] 
00007FF6F44749E4 03 85 10 01 00 00    add         eax,dword ptr [<t_6>] 
00007FF6F44749EA 03 85 18 01 00 00    add         eax,dword ptr [<t_7>] 
00007FF6F44749F0 03 85 20 01 00 00    add         eax,dword ptr [<t_8>] 
00007FF6F44749F6 03 85 28 01 00 00    add         eax,dword ptr [<t_9>] 

显然左折叠类似于这种结合的方式进行执行

(((1 + 2) + 3) + 4) + 5

右折叠则相反

二元折叠示例

前例中如果参数是空的,则会报错,可以通过加上一个数值0(缺省值)来解决编译错误,这就变成了二元折叠

示例:

template<typename ... T>
auto sum_right(T ... t) {
    return (t + ... + 0);
}
template<typename ... T>
auto sum_left(T ...t) {
    return (0 + ... + t);
}

这样一来,即便函数给的参数是空的,也能正常执行编译不报错了

空参数包就是参数包中不含任何参数。

对于大多数操作符,空参数包将会引发编译错误。

对于 && 或 ||,空参数包是合法的,其中 && 的展开结果为 true,||
的展开结果为 false。在逗号 , 操作符中,空参数包也合法,展开为 void()。

示例

计算指定集合内包含指定数值的个数

template<typename R ,typename ...T>
auto count(const R& range, T...t) {
    return (std::count(std::begin(range), std::end(range), t) + ... + 0);
}

int main()
{
    std::vector<int> scores = { 1,2,3,4,5,6,7,8,9,10};
    std::cout << count(scores,3,5,7) << std::endl;          // 3
    std::cout << count("hello world",'o','l') << std::endl; // 5
    return 0;
}

这是右折叠的方式进行函数调用,就是对参数中最右边两个数进行指定运算,结果与从右边起的下一个数继续进行运算,而进行的运算就是这里()里指定的对...的模板参数进行的运算,这里就是std::count(std::begin(range), std::end(range), t) + ...,就是对每一个t都进行这个运算然后都相加

连续打印不同类型的值

template<typename...T>
auto sel_dbgprint(T...t) {
    (std::cout << ... << t) << std::endl;// 折叠表达式需要放在小括号里使用
}

int main()
{
    sel_dbgprint("ERROR::",250,"::妙啊");
    return 0;
}

参考资料:

  • [1] [C++17 折叠表达式 | Greedysky’s Blog](https://greedysky.github.io/2020/12/01/C++17 折叠表达式/)
  • [2] 第 2 章 语言可用性的强化 现代 C++ 教程: 高速上手 C++ 11/14/17/20 - Modern C++ Tutorial: C++ 11/14/17/20 On the Fly (changkun.de)
  • [3] C++17折叠表达式的用法_C++yyds~~~的博客-CSDN博客
编程开发
C++
This post is licensed under CC BY 4.0 by the author.
Share

Further Reading

Apr 12, 2022

《xchg rax,rax》片段分析0x23--模3运算

《xchg rax,rax》片段分析0x23--模3运算

Apr 11, 2022

C++ Iterator 迭代器

迭代器(Iterator)是一种抽象设计理念,通过迭代器可以在不了解容器内部原理的情况下遍历容器。

Apr 10, 2022

C++折叠表达式

C++17折叠表达式的用法

OLDER

漏洞学习--HeapSpray原理

NEWER

C++ Iterator 迭代器

Recently Updated

  • 【置顶】本博客的使用指南&更新计划(2023.3更新)
  • [技能兴鲁2023 决赛 职工组]re-ezalgorithm
  • [Pico CTF 2022]pwn-basic-file-exploit
  • [Pico CTF 2021]pwn-Unsubscriptions Are Free
  • [Pico CTF 2021]pwn-Here's a Libc

Trending Tags

pwn 符号执行 HEVD学习 .NET逆向 病毒分析 CTF 软件安全 《Windows内核编程》 dll注入 树莓派

Contents

©2023 我可是会飞的啊. Some rights reserved.

Using the Halo theme Chirpy