c++ std::variant用法

news2025/4/19 10:09:23

std::variant

Union类型的问题:

  • 无法知道当前使用的类型是什么
  • union无法自动调用底层数据成员的析构函数。联合体无法对其内部的数据属性的生命周期的全面支持,因为当外部代码调用Union时在切换类型,它无法做到对当前使用的对象,并自动调用其析构函数。
  • C/C++没有原生的工具可以检测Union内部当前的活动类型。
  • 不能有non-trivial的成员,比如std::string(从c++ 11起, union原则上可以有non-trivial的成员,但是必须实现特殊的成员函数,比如复制构造函数和析构函数,因为只有通过代码逻辑才能知道哪个成员是可用的。)
  • 不能从union中派生类。

在 C++17 之前,为了改进这些问题,提出了std::variant。

  • 与C语言中传统的 union 类型相同的是,variant 也是联合(union)类型。即 variant 可以存放多种类型的数据,但任何时刻最多只能存放其中一种类型的数据。
  • 与C语言中传统的 union 类型所不同的是,variant 是可辨识的类型安全的联合(union)类型。即 variant 无须借助外力只需要通过查询自身就可辨别实际所存放数据的类型。

std::variant 基础用法

构造函数

std::variant<int, double, std::string> x, y;

x,y是一个可存放 int, double, std::string 这三种类型数据的变体类型的对象

std::in_place_index、std::in_place_type 显式赋值

显式指定当前索引/类型,并使用后续参数进行原地构造

variant<vector<int>, string> v{ std::in_place_index<0>, { 0, 1, 2, 3 } };
variant<vector<int>, string> v{ std::in_place_type<int>, { 0, 1, 2, 3 } };

修改值

赋值和emplace()操作对应于初始化


std::variant<int, int, std::string> var; // sets first int to 0, index()==0
var = "hello"; // sets string, index()==2
var.emplace<1>(42); // sets second int, index()==1

获取当前使用的type 在variant声明中的索引

x = 100.0f;
std::cout << "可变体的活动类型返回的index:" << x.index() << std::endl;

获取std::variant中的值

使用std::get() 或直接std::get()来获取variant中包含的值,std::get(v) 如果变体类型 v 存放的数据类型为 T,那么返回所存放的数据,否则报错

double d = std::get<double>(x);
std::string s = std::get<2>(y);

如果std::variant中当前存储的不是对应Type的值, 则会抛出std::bad_variant_access类型的异常

try
{
    int i = std::get<int>(x);
}
catch (std::bad_variant_access e)
{
    std::cerr << e.what() << std::endl;
}

get_if()

除了会引发异常的std::get<>,也有无异常的 std::get_if() 方法,get_if通常保证std::get在访问可变体时不会抛出bad_variant_access 异常,提供了访问前的类型安全判断。需要自行判断返回的指针类型是否为空。
std::get_if(&v) 如果变体类型 v 存放的数据类型为 T,那么返回所存放数据的指针,否则返回空指针。

int* i = std::get_if<int>(&x);
if (i == nullptr)
{
    std::cout << "wrong type" << std::endl;
}
else
{
    std::cout << "value is " << *i << std::endl;
}

同时具有bool和std::string

如果一个std::variant<>同时有bool和std::string两个备选项,字符串字面量转换为bool比转换为std::string匹配

 #include <iostream>
#include <variant>
 
int main()
{
    std::variant<bool, std::string> v;
    v = "hi"; // OOPS: sets the bool alternative
    std::cout << "index: " << v.index() << '\n';
 
    std::visit([](const auto& val) {std::cout << "value: " << val << '\n'; }, v);
 
    return 0;
}

在这里插入图片描述
字符串常量值被解释为通过Boolean值true初始化变量(true是因为指针不是0)

解决方案

v.emplace<1>("hello"); // explicitly assign to second alternative
v.emplace<std::string>("hello"); // explicitly assign to string alternative
v = std::string{"hello"}; // make sure a string is assigned
 
using namespace std::literals; // make sure a string is assigned
v = "hello"s;

std::holds_alternative(v)

查询变体类型 v 是否存放了 T 类型的数据。

#include <iostream>
#include <string>
#include <variant>

using namespace std;

int main()
{
    variant<int, double, string> v; // v == 0
    v = 1;
    bool has_int = holds_alternative<int>(v);
    bool has_double = holds_alternative<double>(v);
    cout << v.index() << has_int << has_double << get<0>(v) << *get_if<0>(&v) << endl; // 01011
    v = 2.0;
    cout << v.index() << (get_if<int>(&v) == nullptr) << get<1>(v) << get<double>(v) << endl; // 1122
    v = "a";
    cout << v.index() << get<2>(v) << get<string>(v) << endl; // 2aa
}

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

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

相关文章

解决第三方使用iframe内嵌页面时无法正常登录访问的问题

1. 问题描述 在做项目的时候&#xff0c;可能会遇到需要内嵌第三方页面或者第三方软件厂商内嵌我们自己做的web页面&#xff08;这里说的内嵌方式是用iframe的方式&#xff09;&#xff0c;当在使用最新版本的“谷歌浏览器”时就会出现无法正常登录的问题&#xff0c;内嵌的页…

6.基于蜻蜓优化算法 (DA)优化的VMD参数(DA-VMD)

代码原理 基于蜻蜓优化算法 (Dragonfly Algorithm, DA) 优化的 VMD 参数&#xff08;DA-VMD&#xff09;是指使用蜻蜓优化算法对 VMD 方法中的参数进行自动调优和优化。 VMD&#xff08;Variational Mode Decomposition&#xff09;是一种信号分解方法&#xff0c;用于将复杂…

ubuntu借助overlay方案实现重启自动还原

配置重启还原OS 首先&#xff1a;sudo apt install overlayroot 安装一下软件 然后编辑配置文件&#xff1a;/etc/overlayroot.conf * overlayroottmpfs or overlayroottmpfs:PARAMETERS write all changes to a temporary (ram only) backing device A tmpfs mount will …

C语言每日一题(35)有效的括号

力扣网 20 有效的括号 题目描述 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右…

每日一题(LeetCode)----链表--分隔链表

每日一题(LeetCode)----链表–分隔链表 1.题目&#xff08;86. 分隔链表&#xff09; 给你一个链表的头节点 head 和一个特定值 x &#xff0c;请你对链表进行分隔&#xff0c;使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初…

redis运维(十五) 集合

一 集合 ① 概念 集合的元素在redis里面的世界是member集合&#xff1a; setset集合当中不允许重复的元素&#xff0c;而且set集合当中元素是没有顺序的,不存在元素下标 ② sadd、smembers、srem ③ sismember、srandmember、spop、scard spop 命令用于移除集合中的指定 …

数据结构学习笔记——多维数组、矩阵与广义表

目录 一、多维数组&#xff08;一&#xff09;数组的定义&#xff08;二&#xff09;二维数组&#xff08;三&#xff09;多维数组的存储&#xff08;四&#xff09;多维数组的下标的相关计算 二、矩阵&#xff08;一&#xff09;特殊矩阵和稀疏矩阵&#xff08;二&#xff09;…

前端CSS实现响应式TimeLine效果(附源码)

文章目录 纯CSS搭建&#xff0c;先上效果图&#xff08;附有源码&#xff09;视图层 index.htmlindex.css 公用样式文件Main.css 主要的样式文件 纯CSS搭建&#xff0c;先上效果图&#xff08;附有源码&#xff09; 本效果为纯CSS搭建&#xff0c;适配移动端和PC端&#xff01…

FreeRTOS列表和列表项

FreeRTOS内核调度使用了大量的列表&#xff08;list&#xff09;和列表项&#xff08;listitem&#xff09;数据结构。它的源码中涉及到很多列表的操作&#xff0c;对于FreeRTOS来说&#xff0c;列表就是它最基础的一部分&#xff0c;列表被用作FreeRTOS调度器使用&#xff0c;…

SQL 中的 MIN 和 MAX 以及常见函数详解及示例演示

SQL MIN() 和 MAX() 函数 SQL中的MIN()函数和MAX()函数用于查找所选列的最小值和最大值&#xff0c;分别。以下是它们的用法和示例&#xff1a; MIN() 函数 MIN()函数返回所选列的最小值。 示例&#xff1a; 查找Products表中的最低价格&#xff1a; SELECT MIN(Price) F…

搜维尔科技:电影中面部动画的演变,Faceware面部捕捉成后起之秀

面部动画是电影中角色表演的一个重要方面&#xff0c;尤其是在严重依赖电子动画、化妆效果和动作捕捉系统的奇幻电影中。在《龙与地下城&#xff1a;盗贼荣耀》电影中&#xff0c;龙裔角色的面部动画是一个复杂的系统&#xff0c;使该生物在大屏幕上栩栩如生。该系统依赖于一种…

【代码随想录】算法训练计划30

【代码随想录】算法训练计划30 1、51. N 皇后 按照国际象棋的规则&#xff0c;皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。 给你一个整数 n &#xff0c;…

【鸿蒙生态千帆起】HarmonyOS 系统级地图与位置服务,赋能广大开发者

在"与 HarmonyOS 同行&#xff0c;开放生态&#xff0c;共赢未来"为主题的 HUAWEI Developer Day&#xff08;简称 HDD&#xff09;沙龙中&#xff0c;Petal Maps 为开发者们带来了在 HarmonyOS 下地图领域的最新技术探索与实践成果。 得益于 HarmonyOS 一次开发多端…

小程序存在优惠卷遍历,但是歪了

进入小程序&#xff0c;因为是一个小商城&#xff0c;所以照例先查看收货地址是否存在越权&#xff0c;以及能否未授权访问&#xff0c;但是发现不存在这些问题&#xff0c;所以去查看优惠卷 进入领券中心&#xff0c;点击领取优惠券时抓包 发现数据包&#xff0c;存在敏感参数…

【java】想要限制每次查询的结果集不能超过10000行,该如何实现?

文章目录 前言 前言 对于一些Saas化软件&#xff0c;当某个租户在执行查询SQL时&#xff0c;如果查询条件出现了BUG&#xff0c;导致去查了所有租户的数据&#xff0c;这种情况是非常严重的&#xff0c;此时就需要在架构层面做限制&#xff0c;禁止一些特殊SQL的执行&#xff…

.Net6使用WebSocket与前端进行通信

1. 创建类WebSocketTest&#xff1a; using System.Net.WebSockets; using System.Text;namespace WebSocket.Demo {public class WebSocketTest{//当前请求实例System.Net.WebSockets.WebSocket socket null;public async Task DoWork(HttpContext ctx){socket await ctx.We…

还记得高中生物书上的莫斯密码吗?利用Python破解摩斯密码的代码示例!

文章目录 前言摩尔斯电码Python实现摩斯密码对照表加密解密测试 完整代码总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Py…

数学建模之拟合及其代码

发现新天地&#xff0c;欢迎访问Cr不是铬的个人网站 引言 与插值问题不同&#xff0c;在拟合问题中不需要曲线一定经过给定的点。拟合问题的目标是寻求一个函数&#xff08;曲线&#xff09;&#xff0c;使得该曲线在某种准则下与所有的数据点最为接近&#xff0c;即曲线拟合…

【Docker】Docker安装Nginx配置静态资源

1.下载镜像 2.创建nginx配置文件 3.创建nginx容器运行 4.配置nginx静态资源 1.下载镜像 Dockerhub官网&#xff1a;Docker docker pull nginx docker pull nginx下载最新版本 默认latest 下载指定版本docker pull nginx:xxx 2.创建nginx配置文件 启动容器之前要创建nginx…

数字图像处理(冈萨雷斯)学习笔记

目录 一.机器视觉和计算机视觉二.图像处理基础1.什么是图像2.如何访问图像 三.图像仿射变换四.灰度变换 一.机器视觉和计算机视觉 机器视觉(Machine Vision,MV)和计算机视觉(Computer Vision&#xff0c;CV)的区别和联系&#xff1a; 机器视觉更注重广义图像信号(激光&#xff…