C++遍历std::tuple(C++14 ~ C++20)

news2024/11/26 8:45:38

本文展示了遍历std::tuple的方式:

首先比较容易想到的是利用C++14的std::make_index_sequencestd::get结合取值,然后配合std::initializer_list进行包展开:

// since C++14
class Func0 {
    template<typename T, typename F, size_t... I>
    void init(T&& t, F&& f, std::index_sequence<I...>) {
        std::initializer_list<int>{ (f(std::get<I>(t)), 0)... };
    }
public:
    template<typename T, typename F>
    auto operator()(T&& t, F&& f) {
        init(t, f, std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<T>>>{});
    }
};

到了C++17,我们有了折叠表达式(Fold expressions),就可以直白一点了:

// since C++17
class Func1 {
    template<typename T, typename F, size_t... I>
    void init(T&& t, F&& f, std::index_sequence<I...>) {
        ((f(std::get<I>(t))), ...);
    }
public:
    template<typename T, typename F>
    auto operator()(T&& t, F&& f) {
        init(t, f, std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<T>>>{});
    }
};

C++20允许lambda添加模板参数,因此我们可以进一步限制这个遍历器的作用域:

    // since C++20
    auto Func2 = []<typename T, typename F>(T && t, F && f) {
        [&] <size_t ...I>(std::index_sequence<I...>) {
            ((f(std::get<I>(t))), ...);
        }(std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<T>>>{});
    };

然后我们还可以利用C++17提供给我们的std::apply取值:

// since C++17
class Func3 {
public:
    template<typename T, typename F>
    auto operator()(T&& t, F&& f) {
        std::apply(
            [&f](auto&&... args) {
                ((f(args)), ...);
            }, t
        );
    }
};

或者干脆把这个std::apply给拿出来,这种应该算是最简单的:

// since C++17
std::apply(
    [&PrintV](auto&&... args) {
        ((PrintV(args)), ...);
    }, t
);

完整测试程序:

#include <iostream>
#include <tuple>
#include <type_traits>
#include <initializer_list>


// since C++14
class Func0 {
    template<typename T, typename F, size_t... I>
    void init(T&& t, F&& f, std::index_sequence<I...>) {
        std::initializer_list<int>{ (f(std::get<I>(t)), 0)... };
    }
public:
    template<typename T, typename F>
    auto operator()(T&& t, F&& f) {
        init(t, f, std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<T>>>{});
    }
};

// since C++17
class Func1 {
    template<typename T, typename F, size_t... I>
    void init(T&& t, F&& f, std::index_sequence<I...>) {
        ((f(std::get<I>(t))), ...);
    }
public:
    template<typename T, typename F>
    auto operator()(T&& t, F&& f) {
        init(t, f, std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<T>>>{});
    }
};

// since C++17
class Func3 {
public:
    template<typename T, typename F>
    auto operator()(T&& t, F&& f) {
        std::apply(
            [&f](auto&&... args) {
                ((f(args)), ...);
            }, t
        );
    }
};


int main(int argc, char* argv[])
{
    // 测试一下
    // auto t = std::make_tuple(1, 2.f, 3., '4', "5");  // for C++14
    std::tuple t(1, 2.f, 3., '4', "5"); 
    auto PrintV = [](auto&& v) { std::cout << v << ' '; };

    Func0()(t, PrintV);
    std::cout << "\n\n";
    
    Func1()(t, PrintV);
    std::cout << "\n\n";
    
    // since C++20
    auto Func2 = []<typename T, typename F>(T && t, F && f) {
        [&] <size_t ...I>(std::index_sequence<I...>) {
            ((f(std::get<I>(t))), ...);
        }(std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<T>>>{});
    };
    Func2(t, PrintV);
    std::cout << "\n\n";
    
    Func3()(t, PrintV);
    std::cout << "\n\n";

    // since C++17
    std::apply(
        [&PrintV](auto&&... args) {
            ((PrintV(args)), ...);
        }, t
    );
    std::cout << "\n\n";
    return 0;
}

输出结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/881441.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

bert,transformer架构图及面试题

Transformer详解 - mathor atten之后经过一个全连接层残差层归一化 class BertSelfOutput(nn.Module):def __init__(self, config):super().__init__()self.dense nn.Linear(config.hidden_size, config.hidden_size)self.LayerNorm nn.LayerNorm(config.hidden_size, epscon…

疫情打卡 vue+springboot疾病防控管理系统java jsp源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 疫情打卡 vuespringboot 系统有1权限&#xff1a;管理…

vue3+ts-tsconfig.json报错Option ‘importsNotUsedAsValues’

vue3ts-tsconfig.json报错Option ‘importsNotUsedAsValues’ is deprecated and will stop functioning in TypeScript 5.5. Specify compilerOption ‘“ignoreDeprecations”: “5.0”’ to silence this error. Use ‘verbatimModuleSyntax’ instead 自我记录 翻译 选项…

网工软考 | 软考到底考哪个证比较好?

最近来咨询软考的同学比较多&#xff0c;对软考有哪些证书&#xff0c;怎么来选择比较困扰&#xff0c;目前刚好是学习的最佳阶段。 本期就统一来解答一下。 01 软考分为五个专业 计算机软件、计算机网络、计算机应用技术、信息系统和信息服务共五个专业&#xff0c;并在各专…

股市杠杆操作是什么意思?从三方面分析

股市杠杆操作是指投资者通过借用资金进行证券交易&#xff0c;以放大投资回报的一种金融工具。这种操作可以使投资者借用额外的资金进行交易&#xff0c;增加投资收益的潜力&#xff0c;但也伴随着更高的风险。下面从三个方面对股市杠杆操作进行分析。 1. 操作原理和优势&#…

Nginx的块、变量以及重定向

目录 绪论 1、location匹配 1.1 常见的Nginx正则表达式 1.2 正则表达式&#xff1a;匹配的是文件内容 1.3 location匹配uri 1.4 location常用的匹配规则 1.5 location优先级 1.6 匹配小结 1.7 生产环境中的匹配规则 2、nginx的内置变量 3、rewrite 3.1 rewrite作用 …

Spring中bean生命周期的PostProcessor的每个方法的作用

可结合这个博客看 https://blog.csdn.net/riemann_/article/details/118500805、https://cloud.tencent.com/developer/article/1409315、https://blog.csdn.net/qq_43631716/article/details/120239438 本篇内容借鉴于chatgtp,应该有错误&#xff0c;仅作方法应用的参考&#…

python爬虫——爬取天气预报信息

在本文中&#xff0c;我们将学习如何使用代理IP爬取天气预报信息。我们将使用 Python 编写程序&#xff0c;并使用 requests 和 BeautifulSoup 库来获取和解析 HTML。此外&#xff0c;我们还将使用代理服务器来隐藏我们的 IP 地址&#xff0c;以避免被目标网站封禁。 1. 安装必…

数据结构与算法-栈(LIFO)(经典面试题)

一&#xff1a;面试经典 1. 如何设计一个括号匹配的功能&#xff1f;比如给你一串括号让你判断是否符合我们的括号原则&#xff0c; 栈 力扣 2. 如何设计一个浏览器的前进和后退功能&#xff1f; 思想&#xff1a;两个栈&#xff0c;一个栈存放前进栈&…

【BERTopic应用 03/3】:微调参数

一、说明 一般来说&#xff0c;BERTopic 在开箱即用的模型中工作得很好。但是&#xff0c;当您有数百万个数据要处理时&#xff0c;使用基本模型处理数据可能需要一些时间。在这篇文章中&#xff0c;我将向您展示如何微调BERTopic中的一些参数并比较它们的结果。让我们潜入。 二…

简单学生信息管理系统springboot,ssm,ssh学生教师java jsp源代码

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 简单学生信息管理系统springboot,ssm,ssh 系统有1权限…

【C++】移动构造函数

2023年8月15日 概述 移动构造函数是一个特殊的构造函数&#xff0c;用于从一个对象中移动&#xff08;转移&#xff09;资源到另一个对象&#xff0c;而不是进行复制操作。它通常与右值引用一起使用&#xff0c;以实现高效的资源转移&#xff0c;提高性能。 语法 class MyCla…

操作系统-笔记-第二章

目录 二、第二章——【进程】 1、进程的概念 &#xff08;1&#xff09;PID & PCD 进程控制块 &#xff08;2&#xff09;程序段 & 数据段 &#xff08;3&#xff09;特征 &#xff08;特性&#xff09; property &#xff08;4&#xff09;总结 2、进程的状态 …

8个常用的项目管理工具和方法,干货收藏!

在现代商业环境中&#xff0c;高效的项目管理工具和方法是成功实施项目的关键。随着项目的规模和复杂性不断增加&#xff0c;需要科学的方法和先进的工具来确保项目按时交付、控制成本并保持质量。无论是项目管理新手还是经验丰富的专业人士&#xff0c;了解和掌握一些公认好用…

SCF金融公链新加坡启动会 创新驱动未来

新加坡迎来一场引人瞩目的金融科技盛会&#xff0c;SCF金融公链启动会于2023年8月13日盛大举行。这一受瞩目的活动将为金融科技领域注入新的活力&#xff0c;并为广大投资者、合作伙伴以及关注区块链发展的人士提供一个难得的交流平台。 在SCF金融公链启动会上&#xff0c; Wil…

【vue3】固定上导航栏和左侧导航栏,只显示其他内容在主内容区域

实现思路&#xff1a; 在一个单独的vue组件文件中只写出上导航栏和左侧导航栏的内容将你想要展示的页面主内容写到单独的组件中在index.js写路由&#xff0c;将【想要展示的页面主内容的路由】作为【子路由】写在【只写出上导航栏和左侧导航栏的路由】的下面&#xff1b; 在el…

一百五十二、Kettle——Kettle9.3.0本地连接Hive3.1.2(踩坑,亲测有效,附截图)

一、目的 由于先前使用的kettle8.2版本在Linux上安装后&#xff0c;创建共享资源库点击connect时页面为空&#xff0c;后来采用如下方法&#xff0c;在/opt/install/data-integration/ui/menubar.xul文件里添加如下代码 <menuitem id"file-openZiyuanku" label&…

七夕特辑:所以结婚到底有什么好处?

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 伊姐 运营 / SandLiu 卷圈 监制 / 姝琦 封面 / 姝琦Midjourney 产品统筹 / bobo 场地支持 / 声湃轩天津录音间 七夕来临&#xff0c;“记者下班”第一次和大家聊聊亲密关系。 无论是青梅竹马、相识二十年的阿福&#…

私有IP地址有多重要?

私有IP地址是指在局域网中使用的IP地址&#xff0c;而不是公共互联网上可访问的IP地址。私有IP地址不唯一&#xff0c;可以在不同的局域网中重复使用。这种地址分配方式能够有效地节省IP地址资源。 近日&#xff0c;国际互联网协会&#xff08;IATA&#xff09;发布了一项关于私…

twinmotion和lumion相比选哪个更好?

建筑和室内可视化软件彻底改变了设计行业。随着实时渲染技术的引入&#xff0c;建筑师和设计师现在可以在几分钟内创建其设计的逼真渲染。Twinmotion 和 Lumion 是近年来流行的两个这样的程序。在本文中&#xff0c;我们将比较这两种引擎 - 它们有何不同&#xff0c;以及针对特…