【C++】std::variant

上一篇文章讲到了 union,union

union存在很多问题,因此C++17设计了一个新的variant替代原来的union。

union的问题

  1. 无法知道当前使用的类型是什么。
  2. 而且union无法自动调用底层数据成员的析构函数。

这些使得一般只对一些“基本类型”使用union,无法在union里放std::string或者是对象之类的。举个例子:

union CannotUnion
{string vec;
};

这样一个 union 结构,然后在 main 函数里这么写:

    CannotUnion specU = {"I CANNOT"};cout << specU.vec << endl;

甚至于在初始化 specU 的时候,IDE就会发出警告
警告
如果你尝试编译,就会产生如下报错信息:

UnionTest.cpp: In function 'int main()':
UnionTest.cpp:26:36: error: use of deleted function 'CannotUnion::~CannotUnion()'26 |     CannotUnion specU = {"I CANNOT"};|                                    ^
UnionTest.cpp:13:7: note: 'CannotUnion::~CannotUnion()' is implicitly deleted because the default definition would be ill-formed:13 | union CannotUnion|       ^~~~~~~~~~~
UnionTest.cpp:15:12: error: union member 'CannotUnion::vec' with non-trivial 'std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::~basic_string() [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]'15 |     string vec;|            ^~~

C++11以前,union只允许有一些“基本类型”,也就是与C语言相兼容的类型(POD,Plain Old Data)。这些类型可以以二进制的方式转换为C语言的类型。C++11以后,如果非受限联合体内有一个非 POD 的成员,而该成员拥有自定义的构造函数,那么这个非受限联合体的默认构造函数将被编译器删除;其他的特殊成员函数,例如默认拷贝构造函数、拷贝赋值操作符以及析构函数等,也将被删除。

所以想让上面的代码正常运行,把被删除的构造和析构函数还原回来就行了:

union CannotUnion
{string vec;CannotUnion(string vec):vec(vec){};~CannotUnion(){};
};

variant的用法

我一般会提前一段时间接触我马上要写的语法知识。但是我有时候在想,这么复杂的结构真的有必要吗。

variant的用法如下:

#include<iostream>
#include<variant>
#include<string>using namespace std;int main()
{variant<int, string, float> myVar;myVar = "Hello variant";
}

访问

union访问的时候,由于每个成员变量都有自己的变量名,因此直接就可以访问。但是variant不太行,而且还要更麻烦一点。
最简单的就是用get

cout << get<string>(myVar) << endl;

但是这里存在一个问题,如果类型对了那皆大欢喜;类型错了,还要处理抛出的std::bad_variant_access异常:
访问正确和错误
我们可以使用get_if,在判断类型再进行访问。get_if判断类型成功会返回指向数据的指针,判断失败会返回空指针。

    if(auto ptr = get_if<string>(&myVar)){cout << *ptr << endl;}

visit

这个的机制有点像设计模式里的访问者模式(完了我设计模式还没写)

    visit([](auto args){ cout << args << endl; },myVar);

第一个参数是一个函数,函数的参数可以用auto args,后面输出即可。

如果需要针对多个类型的元素进行判断,可以使用类似于访问者模式的写法
以下代码来自:https://blog.csdn.net/qq_21438461/article/details/132659408

// 定义 variant 类型
using MyVariant = std::variant<int, double, std::string>;// 访问者函数对象
struct VariantVisitor {void operator()(int i) const {std::cout << "处理 int: " << i << std::endl;}void operator()(double d) const {std::cout << "处理 double: " << d << std::endl;}void operator()(const std::string& s) const {std::cout << "处理 string: " << s << std::endl;}
};int main() {MyVariant v1 = 10;        // v1 存储 intMyVariant v2 = 3.14;      // v2 存储 doubleMyVariant v3 = "hello";   // v3 存储 stringstd::visit(VariantVisitor(), v1); // 输出: 处理 int: 10std::visit(VariantVisitor(), v2); // 输出: 处理 double: 3.14std::visit(VariantVisitor(), v3); // 输出: 处理 string: helloreturn 0;
}

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

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

相关文章

Redis 安装 redistimeseries.so(时间序列数据类型)教程

配置步骤 1.下载 redistimeseries.so 文件 2.在 redis.conf 中增加配置 loadmodule /home/chenjian/redis-lib/RedisTimeSeries/redistimeseries.so DUPLICATE_POLICY LAST3.重启 Redis 服务 4.连接客户端&#xff0c;测试 RedisTimeSeries 相关命令&#xff0c;下图表明 R…

Java玩转《啊哈算法》排序之快速排序

心无挂碍&#xff0c;无挂碍故&#xff0c;无有恐怖&#xff0c;远离颠倒梦想&#xff0c;究竟涅槃。 地图 引子代码地址快速排序核心代码优劣完整代码演示 课后习题 引子 搭嘎好&#xff01;本人最近看的《啊哈算法》这本书写的确实不错&#xff0c;生动形象&#xff0c;在保…

数据要素市场化建设,贝叶斯纳什均衡是博弈论 的一个概念

目录 数据要素市场化建设 数据流通视野下企业数据权利配置论

安全耐用 一路稳行 极固轮胎3大系列产品重磅上市

临近年关&#xff0c;全国范围内雨雪天气多发&#xff0c;让极端天气环境下的行车安全再次成为热议话题。路面寒冷湿滑&#xff0c;交通事故频发&#xff0c;也让大家开始关注一个话题&#xff1a;如何确保汽车在湿滑路面上的安全系数&#xff1f;或者说&#xff0c;如果遭遇类…

如何让wordpress首页只显示某一篇文章全部内容?在您的主页显示选择

大多数WordPress站点首页默认都是显示最新发布的文章列表&#xff0c;不过有些站点比较特殊&#xff0c;只想显示某一篇文章的全部内容&#xff0c;那么应该怎么设置呢&#xff1f; 其实&#xff0c;WordPress后台 >> 设置 >> 阅读 >> 在“您的主页显示”中…

基于flask的个人博客项目从0到1

项目展示 首页 文章时间线页面 笔记页面 留言页面 关于页面 后台页面-文章管理 后台页面-笔记页面 后台页面-分类 后台管理-新增标签 后台管理-标签页面 后台管理-新增标签 后台管理-关于页面 2.项目详述 该博客开源地址点击跳转&#xff0c;该项目已部署上线&#xff0c;…

IP-guard发布新版本4.83.907.0

IP-guard发布新版本4.83.907.0 新版本下载地址&#xff1a;http://www.tec-development.com/down/IPguard/Release/V4/IPguard4.83.0907.0.zip?sB5AE698645948F9722C96C71C67591FA13AAAE13FE90D068E9488F5B2F138000 新版本升级地址&#xff1a;http://www.tec-development.c…

《HTML 简易速速上手小册》第8章:HTML 表单高级技术(2024 最新版)

文章目录 8.1 数据收集与处理8.1.1 基础知识8.1.2 案例 1&#xff1a;创建一个注册表单8.1.3 案例 2&#xff1a;创建一个调查问卷表单8.1.4 案例 3&#xff1a;创建一个动态添加输入字段的表单 8.2 定制化表单元素8.2.1 基础知识8.2.2 案例 1&#xff1a;创建一个带有定制选择…

【GAMES101】Lecture 12 阴影 Shadow Mapping

这里是光栅化的最后一部分&#xff0c;讲这个光栅化里面怎么实现这个阴影 实际上阴影就是光源看不到的地方但是是我们能看到的地方&#xff0c;那这个地方就应该有阴影&#xff0c;那具体怎么做呢&#xff0c;这个就叫做Shadow Mapping&#xff0c;分两步做 我们之前说过这个解…

【Spring Boot 3】【@Scheduled】多线程执行定时任务

【Spring Boot 3】【@Scheduled】多线程执行定时任务 背景介绍开发环境开发步骤及源码工程目录结构总结背景 软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新…

Stable Diffusion系列(四):提示词规则与使用

文章目录 基础规则高级规则插件使用基于相机镜头增强提示词常用提示词总结奇特提示词珍藏 基础规则 所谓提示词&#xff0c;也就是文生图中的文&#xff0c;由连贯的英语单词或句子组成。其最基础的规则是&#xff1a; 不同提示词之间需要用英文逗号分隔&#xff0c;空格和换…

基于大数据的B站数据分析系统的设计与实现

摘要&#xff1a;随着B站&#xff08;哔哩哔哩网&#xff09;在国内视频分享平台的崛起&#xff0c;用户规模和数据量不断增加。为了更好地理解和利用这些海量的B站数据&#xff0c;设计并实现了一套基于Python的B站数据分析系统。该系统采用了layui作为前端框架、Flask作为后端…

mfc140.dll找不到了要怎么解决?教你多种修复mfc140.dll的方法

遭遇 mfc140.dll 文件缺失的状况时&#xff0c;首要任务是保持冷静&#xff0c;并深入理解问题所在&#xff0c;随后按照科学的方法来应对这一挑战。本篇文章概述了多种应对策略&#xff0c;从适合新手的基本步骤到针对有技术基础用户的高级方案&#xff0c;各种手段都能有效地…

linux系统查看占用cpu程序

目录 一&#xff1a;top 二&#xff1a; ps 三&#xff1a;perf 四&#xff1a;/proc/stat 五&#xff1a;pidstat 一&#xff1a;top 使用 top 命令&#xff1a;在终端中输入 top 命令&#xff0c;系统会显示当前正在运行的进程和它们的资源占用情况。默认情况下&#…

awk 文本处理工具三剑客

一、什么是awk 1.1 awk 基本概念 awk&#xff08;语言&#xff09;&#xff1a; 读取一行处理一行 是一个功能强大的编辑工具&#xff0c;逐行读取输入文本&#xff0c;默认以空格或tab键作为分隔符作为分隔&#xff0c;并按模式或者条件执行编辑命令。而awk比较倾向于将一行…

【Luna】AirPlaySimulator

AirPlaySimulator 镜像路径的“完整”平台测试器。该工具用于为合作伙伴提供可重复的测试用例。之所以说“完整”,是因为它既充当发送方,又充当SDK,所以这里来自测试文件的数据和来自发送方设备的数据之间没有太大的区别。 #用法: 有两个可能的初始设置步骤: 1)运行AirPl…

gstreamer学习笔记

gstreamer学习笔记 1. GStreamer中文教程1.1. GStreamer的elements仅有四种状态 2. demo2.1. hello-world 1. GStreamer中文教程 GStreamer中文教程 gstreamer-example代码列子 1.1. GStreamer的elements仅有四种状态 GStreamer的elements仅有四种状态&#xff0c;四种状态从…

【网络】:网络套接字(UDP)

网络套接字 一.网络字节序二.端口号三.socket1.常见的API2.封装UdpSocket 四.地址转换函数 网络通信的本质就是进程间通信。 一.网络字节序 我们已经知道,内存中的多字节数据相对于内存地址有大端和小端之分, 磁盘文件中的多字节数据相对于文件中的偏移地址也有大端小端之分,网…

签名证书文件泄漏不要慌,Rotate signing带你无缝更换新签名

先说结论:如果oldkey.jks 泄漏了&#xff0c;可以直接换一个新的签名newkey.jks,然后使用oldkey.jks和newkey.jks共同对新APK进行签名。效果如下&#xff1a; 一、覆盖安装效果是&#xff1a; &#xff08;一&#xff09;可覆盖安装情况&#xff1a; 1.oldkey签名的包可以被o…

UE5.1_常用节点说明(经常忘记怎么用?)(常改)

UE5.1_常用节点说明&#xff08;经常忘记怎么用&#xff1f;&#xff09;&#xff08;常改&#xff09; 1. Gate——门节点。只有当门是Open状态才会执行Exit后面的代码。 Open开门&#xff1b;Close关门&#xff1b;Toggle开门和关门交替。 2. 关于控制ArmLength即控制相机前…