【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 存储 int
    MyVariant v2 = 3.14;      // v2 存储 double
    MyVariant v3 = "hello";   // v3 存储 string

    std::visit(VariantVisitor(), v1); // 输出: 处理 int: 10
    std::visit(VariantVisitor(), v2); // 输出: 处理 double: 3.14
    std::visit(VariantVisitor(), v3); // 输出: 处理 string: hello

    return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

处理 Maven jar 包下载失败问题

目录 1、配置国内 Maven 源 配置和检测 settings.xml 配置国内源 2、删除本地 maven 创库的 jar 重新下载 3、其他问题 一般情况下 maven jar 包下载不成功可能有两种情况&#xff1a; 1&#xff09;没有配置国内源 2&#xff09;jar 包需要重新下载 下面详细讲解如何解决这两…

机器学习 | 利用Pandas进入高级数据分析领域

目录 初识Pandas Pandas数据结构 基本数据操作 DataFrame运算 文件读取与存储 高级数据处理 初识Pandas Pandas是2008年WesMcKinney开发出的库&#xff0c;专门用于数据挖掘的开源python库&#xff0c;以Numpy为基础&#xff0c;借力Numpy模块在计算方面性能高的优势&am…

【计网·湖科大·思科】实验二 计算机网络的寻址问题

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

物联网IOT: 风浆叶片拧紧装配及实时监测系统

某大型风电设备,通过机器人应用与精益化生产体系的融合,打造出行业领先的具备柔性生产能力的“脉动式”生产体系。同时在关键工序上。其中,在叶片装配等关键工序上使用由智能机器人代替人工,以提高生产的效率和装配质量可靠性,将六轴机器人、视觉系统、光电系统、液压、气动、伺…

RISC-V常用汇编指令

RISC-V寄存器表&#xff1a; RISC-V和常用的x86汇编语言存在许多的不同之处&#xff0c;下面将列出其中部分指令作用&#xff1a; 指令语法描述addiaddi rd,rs1,imm将寄存器rs1的值与立即数imm相加并存入寄存器rdldld t0, 0(t1)将t1的值加上0,将这个值作为地址&#xff0c;取…

科技助力“双碳”:墨水屏电子桌牌在绿色办公中的作用

随着科技的发展&#xff0c;人们对绿色环境可持续发展也越来越重视&#xff0c;所以&#xff0c;我国在几年前&#xff0c;就提出了“双碳”政策&#xff08;即碳达峰与碳中和的简称。2020年9月中国明确提出2030年“碳达峰”与2060年“碳中和”目标&#xff09;&#xff0c;而作…

DNS欺骗

DNS(域名系统)作为当前全球最大 、最复杂的分布式层次数据库系统&#xff0c;具有着开放、庞大、复杂的特性。它为全球用户提供域名解析服务&#xff0c;是互联网的重要基础设施。但由于其在设计之初未考虑安全性、人为破坏等因素 &#xff0c;DNS系统在互联网高度发达的今天面…

Python之数据可视化(地图)

目录 一 基础地图应用 二 全国疫情图 一 数据准备 二 数据处理 二 湖北省疫情图 一 数据准备 二 数据处理 一 基础地图应用 导入map地图对象 from pyecharts.charts import Map map Map() 写入数据 data [("北京市",100),("上海市"…

详细解读vcruntime140_1.dll修复的手段,如何快速解决vcruntime140_1.dll丢失问题

当出现“无法找到vcruntime140_1.dll”或程序“未能正常启动”时&#xff0c;这通常指示系统中缺失了一个关键文件&#xff1a;vcruntime140_1.dll。作为Visual C Redistributable组件的一部分&#xff0c;这个小文件在很多用Visual Studio编译的C程序运行时发挥着重要作用。解…

OJ_叠框问题

问题描述 c语言实现 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<string.h> using namespace std;int main() {int n; //存放外框尺寸int a,b; //存放两个字符char matrix[100][100] { 0 };//全部初始化为休止符/0while (scanf("%d %c %c&…

【开源】基于JAVA的实验室耗材管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 耗材档案模块2.2 耗材入库模块2.3 耗材出库模块2.4 耗材申请模块2.5 耗材审核模块 三、系统展示四、核心代码4.1 查询耗材品类4.2 查询资产出库清单4.3 资产出库4.4 查询入库单4.5 资产入库 五、免责说明 一、摘要 1.1…

IntelliJ IDEA 快捷键大全

IntelliJ IDEA 快捷键大全 一、文本编辑二、构建、编译项目 一、文本编辑 CtrlN 查找类 CtrlN 查找文件 CtrlF 查找文本 可以根据需求去选择红框内的选项 CtrlX 剪切 剪切选中文本&#xff0c;如果未选中则剪切当前行CtrlC 复制 复制选中文本&#xff0c;如果未选中则复制当前…

机房环境动力监控系统:S275远程控制网关助力高效管理

现场问题 1、机房安全隐患 机房存在意外断电、温湿度过高过低、漏水断路等隐患&#xff0c;传统监测手段难以提前发现和预警。 2、机房远程运维困难 因环境改变、非授权活动、设备状态变化等引起的事故&#xff0c;难以满足机房远程运维的可靠管控要求。 3、机房改造成本高…

数论Leetcode204. 计数质数、Leetcode858. 镜面反射、Leetcode952. 按公因数计算最大组件大小

Leetcode204. 计数质数 题目 给定整数 n &#xff0c;返回 所有小于非负整数 n 的质数的数量 。 代码 class Solution:def countPrimes(self, n: int) -> int:if n < 2:return 0prime_arr [1 for _ in range(n)]prime_arr[0], prime_arr[1] 0, 0ls list()for i in…

南方故乡吹来的风

故乡的风 - 张明敏 词&#xff1a;刘因国 曲&#xff1a;刘因国 南方故乡吹来的风 带着潮水的呼唤 吹着你的秀发 飘散着茉莉的香 茉莉的香哟 南方故乡吹来的风 带着渔船的归航 吹着你的欢畅 吹着渔帆点点醉哟 点点的醉哟 远方的姑娘 你是否听见 我的心在嘿哟 你…

缓存技术—redis

一、redis介绍 1.什么是NoSQL NosQL (Not-Only:sQL)&#xff0c;泛指非关系型的数据库(关系型数据库: 以二维表形式存储数据) 非关系型的数据库现在成了一个极其热门的新领域&#xff0c;发展非常迅速。而传统的关系数据库在应付超大规模和高并发的网站已经显得力不从…

设计模式-生成器设计模式

什么是生成器设计模式 众所周知我们设计代码的时候要将代码设计出模块化的&#xff0c;一个功能是一个模块&#xff0c;那么生成器设计模式&#xff0c;是将一个类再度进行了一个拆分&#xff0c;让一个类的内部进行了单一职责化&#xff0c;其实我们在平时开发的时候就会不经…

金智易表通构建学生缴费数据查询+帆软构建缴费大数据报表并整合到微服务

使用金智易表通挂接外部数据,快速建设查询类服务,本次构建学生欠费数据查询,共有3块设计,规划如下: 1、欠费明细查询:学校领导和财务处等部门可查询全校欠费学生明细数据;各二级学院教职工可查询本二级学院欠费学生明细数据。 2、大数据统计报表:从应收总额、欠费总额…

Debezium发布历史90

原文地址&#xff1a; https://debezium.io/blog/2020/04/09/using-debezium-with-apicurio-api-schema-registry/ 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. 将 Debezium 与 A​​picurio API 和架构注册表…

每次请求sessionid变化【SpringBoot+Vue】

引言&#xff1a;花了一晚上的时间&#xff0c;终于把问题解决了&#xff0c;一开始后端做完后,用apifox所有接口测试都是可以的,但当前端跑起来后发现接收不到后端的数据。 当我写完前后端&#xff0c;主页面和获取当前页面信息接口后&#xff0c;配置了cros注解 CrossOrigin…