C++17中std::variant的使用

      可变参数模板类std::variant表示类型安全联合体(type-safe union)。std::variant的实例在任何给定时间要么保存其替代类型之一的值,要么在错误的情况下无值。
      与union一样,如果std::variant保存某个对象类型T的值,则T的对象表示形式将直接在std::variant本身的对象表示形式中分配。不允许std::variant分配额外的(动态)内存,std::variant不会分配堆内存。
      不允许std::variant保存引用、数组或void类型(references, arrays, or the type void)。空的std::variant也是格式错误的。
      允许std::variant多次保存相同类型,并保存相同类型的不同cv限定(cv-qualified versions)版本。
      std::variant允许你以灵活且类型安全的方式处理多种数据类型。std::variant可以存储各种数据类型的值,包括基本类型(int、double等)、用户定义类型(自定义类或结构),甚至其它std::variant。
      使用std::in_place_type或std::in_place_index可对多个值初始化,也可以使用它们在初始化时解决歧义问题。
      和std::optional、std::any一样,std::variant对象是值语义。也就是说,拷贝被实现为深拷贝。
      std::variant持有的值有若干候选项(alternative),这些选项通常有不同的类型。然而,两个不同选项的类型也有可能相同
      初始化和赋值操作都会查找最匹配的选项。如果类型不能精确匹配,可能会发生奇怪的事情。std::variant没有空的状态,这意味着每一个构造好的std::variant对象,至少调用了一次构造函数。默认构造函数会调用第一个选项类型的默认构造函数。如果第一个类型没有默认构造函数,那么调用std::variant的默认构造函数将会导致编译期错误。结构体std::monostate可以处理这种情况。std::monostate可以作为第一个选项类型来保证std::variant能默认构造。

namespace {template<class T>
auto& operator<<(std::ostream& out, const std::vector<T>& v)
{out << "{";for (const auto& e : v)out << e << " ";return out << "}";
}struct S {S(int i) : i(i) {}int i;
};class Derived : public std::variant<int, std::string> { };} // namespaceint test_variant_init()
{std::variant<int, float> var1;std::cout << "index: " << var1.index() << ", value: " << std::get<int>(var1) << "\n"; // index: 0, value: 0std::variant<std::string, int> var2{ "CHINA" };std::cout << "index: " << var2.index() << ", value: " << std::get<std::string>(var2) << "\n"; // index: 0, value: CHINAstd::variant<std::string, int> var3{ 66 };std::cout << "index: " << var3.index() << ", value: " << std::get<int>(var3) << "\n"; // index: 1, value: 66std::variant<std::vector<int>, std::string, float> var4{ std::in_place_type<std::string>, "CHINA" };std::cout << "index: " << var4.index() << ", value: " << std::get<std::string>(var4) << "\n"; // index: 1, value: CHINAstd::variant<std::string, std::vector<int>, float> var5{ std::in_place_type<std::vector<int>>, {1, 2, 3, 4, 5} };std::cout << "index: " << var5.index() << ", value: " << std::get<std::vector<int>>(var5) << "\n"; // index: 1, value: {1 2 3 4 5 }std::variant<std::string, bool, std::vector<std::string>> var6{ std::in_place_index<2>, 5, "hi" };std::cout << "index: " << var6.index() << ", value: " << std::get<std::vector<std::string>>(var6) << "\n"; // index: 2, value: {hi hi hi hi hi }//std::variant<S> var7; // error C2512: "std::variant<`anonymous-namespace'::S>::variant": 没有合适的默认构造函数可用std::variant<std::monostate, S> var7;std::cout << "index: " << var7.index() << "\n"; // index: 0if (std::holds_alternative<std::monostate>(var7))std::cout << "var7 has monostate\n"; // var7 has monostatevar7 = std::monostate{};return 0;
}

      std::variant相关函数
      (1).index:返回存储在std::variant中的数据类型从零开始的索引;
      (2).emplace: 就地(in place)构造std::variant的值;若已存储值,则首先销毁当前存储的值,然后再初始化;
      (3).holds_alternative: 检查std::variant当前是否拥有给定类型;返回bool类型;
      (4).get:从std::variant中检索给定索引或类型(如果类型是唯一的)的值,如果不匹配,则抛出异常;返回存储值的引用
      (5).get_if:获取指向给定索引或类型(如果唯一)的std::variant值的指针,出错时返回nullptr,它的参数是一个指针
      (6).valueless_by_exception:检查std::variant是否处于无效状态;
      (7).std::variant_npos:std::variant处于无效状态时,std::variant的索引值;
      (8).std::swap:交换两个std::variant对象的值;
      (9).operator==, !=, <, <=, >, >=:比较两个std::variant对象;
      std::variant也支持move语义

int test_variant_functions()
{std::variant<int, float, std::string> var1{ 66.6f };std::cout << "index: " << var1.index() << ", value: " << std::get<float>(var1) << "\n"; // index: 1, value: 66.6var1.emplace<2>("CHINA");std::cout << "index: " << var1.index() << ", value: " << std::get<std::string>(var1) << "\n"; // index: 2, value: CHINAvar1.emplace<0>(88);std::cout << "index: " << var1.index() << ", value: " << std::get<int>(var1) << "\n"; // index: 0, value: 88std::cout << std::boolalpha<< "holds int: " << std::holds_alternative<int>(var1)<< ", holds string: " << std::holds_alternative<std::string>(var1) << "\n"; // holds int: true, holds string: falseif (std::holds_alternative<int>(var1))std::cout << "var1 type: int\n"; // var1 type : intstd::variant<std::string, int, float, std::vector<float>> var2;var2 = std::get<int>(var1);std::cout << "index: " << var2.index() << ", value: " << std::get<int>(var2) << "\n"; // index: 1, value: 88var2 = std::get<0>(var1); // <==> var2 = std::get<int>(var1);std::cout << "index: " << var2.index() << ", value: " << std::get<int>(var2) << "\n"; // index: 1, value: 88std::get<0>(var1) = 99;std::cout << "index: " << var1.index() << ", value: " << std::get<int>(var1) << "\n"; // index: 0, value: 99try {//var2 = std::get<2>(var1);var2 = std::get<std::string>(var1);} catch (std::bad_variant_access const& ex) {std::cout << "exception: " << ex.what() << "\n"; // windows: exception: bad variant access; linux: exception: std::get:wrong index for variant}std::variant<std::string, std::string> var3;std::get<0>(var3) = "China";std::cout << "index: " << var3.index() << ", value: " << std::get<0>(var3) << "\n"; // index: 0, value: Chinavar3.emplace<1>("Beijing");std::cout << "index: " << var3.index() << ", value: " << std::get<1>(var3) << "\n"; // index: 1, value: Beijingauto check_value = [](const std::variant<int, float>& v) {if (const int* pval = std::get_if<int>(&v))std::cout << "variant value: " << *pval << '\n';elsestd::cout << "failed to get value" << '\n';};std::variant<int, float> var4{ 12 }, var5{ 3.f };check_value(var4); // variant value: 12check_value(var5); // failed to get valueDerived var6{ "Beijing" };std::cout << "index:" << var6.index() << ", value: " << std::get<1>(var6) << "\n"; // index:1, value: Beijingstd::swap(var4, var5);std::cout << "var4 index: " << var4.index() << ", value: " << std::get<1>(var4) << "\n"; // var4 index: 1, value: 3std::cout << "var5 index: " << var5.index() << ", value: " << std::get<0>(var5) << "\n"; // var5 index: 0, value: 12std::cout << std::boolalpha << "var4 == var5: " << (var4 == var5) << "\n"; // var4 == var5: falsestd::variant<std::string, std::string> var7{ std::in_place_index<1>, "China" }, var8;std::cout << "index: " << var7.index() << ", value: " << std::get<1>(var7) << "\n"; // index: 1, value: Chinavar7.emplace<0>("Bejing");std::cout << "index: " << var7.index() << ", value: " << std::get<0>(var7) << "\n"; // index: 0, value: Bejingvar8 = std::move(var7);std::cout << "index: " << var7.index() << ", value: " << std::get<0>(var7) << "\n"; // index: 0, value:std::cout << "index: " << var8.index() << ", value: " << std::get<0>(var8) << "\n"; // index: 0, value: Bejingreturn 0;
}

      执行结果如下图所示:

      GitHub:https://github.com/fengbingchun/Messy_Test

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

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

相关文章

在 C# 程序中注入恶意 DLL

为什么 Windbg 附加到 C# 程序后&#xff0c;程序就处于中断状态了&#xff1f;它到底是如何实现的&#xff1f;其实简而言之就是线程的远程注入&#xff0c;这一篇就展开说一下。 实现原理 1. 基本思路 WinDbg 在附加进程的时候&#xff0c;会注入一个线程到 C# 进程 中&…

【LeetCode刷题-双指针】--259.较小的三数之和

259.较小的三数之和 方法&#xff1a;排序双指针 class Solution {public int threeSumSmaller(int[] nums, int target) {Arrays.sort(nums);int k 0;for(int i 0;i<nums.length;i){int start i 1,end nums.length - 1;while(start < end){int sum nums[start] …

趣学python编程 (一、计算机发展历史)

未来是高度科技化和智能化的时代。过去不识字的叫“文盲”&#xff0c;如今不懂点计算机知识&#xff0c;则可能是新时代的“文盲”。不论从事什么行业&#xff0c;了解下计算机和编程都是有益的。Python 连续多年占据最受欢迎的编程语言榜首&#xff0c;未来Python有机会成为像…

Web之HTML笔记

Web之HTML、CSS、JS Web标准一、HTML&#xff08;超文本标记语言&#xff09;HTML 基本结构标签常用标签1.font标签2.p标签3.注释4.h系列标题5.img6.超链接a7.列表8.表格9.表单 Web之CSS笔记 Web标准 结构标准用于对网页元素进行整理和分类(HTML)表现标准用于设置网页元素的版…

mysql服务器数据同步

在Linux和Windows之间实现MySQL服务器数据的同步。下面是一些常见的方法和工具&#xff1a; 复制&#xff08;Replication&#xff09;&#xff1a;MySQL复制是一种常见的数据同步技术&#xff0c;可用于将一个MySQL服务器的数据复制到其他服务器。您可以设置主服务器&#xff…

Systemverilog中Clocking blocks

1. clocking block的作用 Clocking block可以将timing和synchronization detail从testbench的structural、functional和procedural elements中分离出来&#xff0c;因此sample timming和clocking block信号的驱动会隐含相对于clocking block的clock了&#xff0c;这就使得对一些…

【LeetCode刷题-滑动窗口】--345.反转字符串中的元音字母

345.反转字符串中的元音字母 class Solution {public String reverseVowels(String s) {int len s.length();if(len < 2){return s;}char[] charArray s.toCharArray();int left 0,right len - 1;while(true){while(left < len && checkVowels(charArray[lef…

智能配电系统解决方案

智能配电系统解决方案是一种集成了先进技术和智能化功能的配电系统&#xff0c;它能够提高电力系统的效率、可靠性和安全性。力安科技智能配电系统解决方案依托电易云-智慧电力物联网&#xff0c;具体实施的方案如下&#xff1a; 智能化设备和传感器&#xff1a;采用智能化的开…

【开源】基于Vue.js的音乐偏好度推荐系统的设计和实现

项目编号&#xff1a; S 012 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S012&#xff0c;文末获取源码。} 项目编号&#xff1a;S012&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、系统设计2.1 功能模块设计2.1.1 音乐档案模块2.1…

[Kettle] 字段处理

1.增加常量 常量是指在计算机程序运行过程中其值不能改变的量 常量可以是任何的数据类型&#xff0c;例如&#xff0c;圆周率"3.141159"、中国首都"北京"等都可以是常量 增加常量是指在数据中增加一个字段&#xff0c;并给字段设置一个固定的值 数据源…

手搓哈希表、列表、队列,只为了用C语言快速求解华容道游戏,我不是大佬,只是一个游戏算法爱好者

背景 多年前曾经写过C语言求解华容道&#xff0c;当时没有用到哈希表&#xff0c;导致整个查重搜索数组过大&#xff0c;每次求解都得花上数分钟的时间&#xff0c;如今时过境迁&#xff0c;对数据结构和算法有了更深的理解&#xff0c;所以得把这一块补上了。(其实就是最近想…

(论文阅读46-50)图像描述2

46.文献阅读笔记 简介 题目 Learning a Recurrent Visual Representation for Image Caption Generation 作者 Xinlei Chen, C. Lawrence Zitnick, arXiv:1411.5654. 原文链接 http://www.cs.cmu.edu/~xinleic/papers/cvpr15_rnn.pdf 关键词 2014年rnn图像特征和文本特…