C++17折叠表达式(Fold Expressions)

语法

template<typename... Args>
  1. ( args op ... )(一元右折叠)
  2. ( ... op args)(一元左折叠)
  3. ( args op ... op init )(二元右折叠)
  4. ( init op ... op args)(二元左折叠)

说明

  • op - 下列 32 个二元操作符之一:+ - * / % ^ & | = < > << >> += -= *= /= %= ^= &= |= <<= >>= == != <= >= && || , .* ->*。在二元折叠中,两个 op 必须相同。
  • pack - 包含未展开的参数包的表达式
  • init - 不包含未展开的参数包的表达式
  • 注意,括号是折叠表达式的必要组成部分。

注意

如果作为 initpack 的表达式包含最高级别低于 cast 的优先级的操作符,则必须将其括在括号内:

template<typename... Args>
int sum(Args&&... args)
{
//  return (args + ... + 1 * 2);   // 错误:*操作符优先级低于 cast
    return (args + ... + (1 * 2)); // 正确
}

解释

对折叠表达式的实例化会按照以下方式展开表达式 e

  1. 一元右折叠 (E op ...) 变成 (E op (... op (EN-1 op EN)))
  2. 一元左折叠 (... op E) 变成 (((E1 op E2) op ...) op EN)
  3. 二元右折叠 (E op ... op I) 变成 (E1 op (... op (EN−1 op (EN op I))))
  4. 二元左折叠 (I op ... op E) 变成 ((((I op E1) op E2) op ...) op EN)(其中 N 是参数包扩展中的元素数)

例如,

template<typename... Args>
bool all(Args... args) { return (... && args); }
 
bool b = all(true, true, true, false);
// 在 all() 中,一元左折叠展开为
//  return ((true && true) && true) && false;
// b 为 false

综合示例

记住Args是模板参数包,展开后是每个参数类型,args是函数参数包,展开后是一个个的参数变量

#include <climits>
#include <concepts>
#include <cstdint>
#include <iostream>
#include <type_traits>
#include <utility>
#include <vector>
 
template<typename... Args>
void printer(Args&&... args)
{
    (std::cout << ... << args) << '\n';
    // 展开后:std::cout << arg1 << arg2 << ... << argN
}
 
template<typename T, typename... Args>
void push_back_vec(std::vector<T>& v, Args&&... args)
{
    static_assert((std::is_constructible_v<T, Args&&> && ...));
    (v.push_back(std::forward<Args>(args)), ...);
    // 两个折叠表达式,展开后相当于
    // std::is_constructible_v<T, Arg1&&> && std::is_constructible_v<T, Arg2&&> && ... && std::is_constructible_v<T, ArgN&&>
    // v.push_back(std::forward<Arg1>(arg1)), v.push_back(std::forward<Arg2>(arg2)), ..., v.push_back(std::forward<ArgN>(argN))
}

// 这个函数的目的是将输入的整数 `i` 进行字节交换,并返回结果
template<class T, std::size_t... dummy_pack>
constexpr T bswap_impl(T i, std::index_sequence<dummy_pack...>)
{
    T low_byte_mask = (unsigned char)-1;
    T ret{};
    ([&]
    {
        (void)dummy_pack;
        ret <<= CHAR_BIT;
        ret |= i & low_byte_mask;
        i >>= CHAR_BIT;
    }(), ...);
	// ([&] { ... }(), [&] { ... }(), ...)
    return ret;
}

 
int main()
{
    printer(1, 2, 3, "abc");
 
    std::vector<int> v;
    push_back_vec(v, 6, 2, 45, 12);
    push_back_vec(v, 1, 2, 9);
    for (int i : v)
        std::cout << i << ' ';
    std::cout << '\n';
}

输出:

123abc
6 2 45 12 1 2 9
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

宗浩多捞

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

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

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

打赏作者

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

抵扣说明:

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

余额充值