(C++23) expected 基础使用

文章目录

  • ⭐前言
  • ⭐expected
    • 🎛️基础使用
    • 🎛️单子操作 (Monadic operations)
      • 🎚️and_then & or_else
      • 🎚️transform & transform_error
  • ⭐END
    • 🌟跋
    • 🌟交流方式

⭐前言

在 C++17 中,提出了 optional 的可选项类型。但是该类型仅能表示二元状态,true | false 但在实际业务常见成功与否可以只用一个flag表示,但失败的原因却多种多样,需要以一种更丰富的形式表示。

因此在 C++23 中正式规范了std::expected,操作方式与原先的std::optional相似,又扩展了一些统一的处理方案。

同时这些方法在 C++23 中也为 std::optional 提供。

⭐expected

下面以一个获取星期几的字符串的demo为例子来表示。

🎛️基础使用

操作以使用 std::optional 一致,但这里多了一项 error 的选项。

#include <ctime>
#include <expected>
#include <iostream>
#include <string>
#include <typeinfo>enum struct ParseError : int {Below,  // (<0)Above   // (>6)
};std::expected<std::string, ParseError> get_weekDay(int d) {if (d < 0) {return std::unexpected(ParseError::Below);} else if (d > 6) {return std::unexpected(ParseError::Above);}// C++20 指定初始化std::tm t{.tm_wday = d};char    buffer[16];std::strftime(buffer, sizeof(buffer), "%A", &t);return std::string(buffer);
}void test(int d) {auto ex = get_weekDay(d);if (ex.has_value()) {std::cout << ex.value() << std::endl;} else {if (ex.error() == ParseError::Below) {std::cout << "ParseError::Below" << std::endl;} else if (ex.error() == ParseError::Above) {std::cout << "ParseError::Above" << std::endl;} else {std::cout << ex.value_or("ParseError") << std::endl;}}
}int main() {test(-1);test(0);test(114514);
}

🎛️单子操作 (Monadic operations)

下面仅对上面 demo 的 void test(int) 函数进行修改

一般来说 Monadic operations 会被翻译成一元操作,或者单目操作。不知道为什么std::expected - cppreference.com 这里翻译成单子操作。

🎚️and_then & or_else

and_then() 如果 *this:

  • 表示预期值,那么调用 f 并返回它的结果。

  • 否则返回一个包含非预期值的 std::expected 对象,以 *this 的非预期值初始化该值。

or_else 如果 *this:

  • 包含非预期值,那么以 *this 的非预期值作为实参调用 f 并返回它的结果。

  • 否则返回一个表示预期值的 std::expected 对象。

因此两者的使用非常灵活,使用得当可以非常遍历的进行链式编程。

这个写法让我回想起以前写 javascript 的时候。

void test(int d) {auto ex = get_weekDay(d);ex/*** 若存在预期值则返回给定的函数在其上的结果,否则返回 expected 本身*/.and_then([](const auto& e) -> std::expected<std::string, ParseError> {std::cout << "[and_then] Type:" << typeid(e).name() << std::endl;std::cout << e << std::endl;return {e};})/*** 若 expected 含有预期值则返回其自身,否则返回给定的函数在非预期值上的结果*/.or_else([](const auto& e) -> std::expected<std::string, ParseError> {std::cout << "[or_else] Type:" << typeid(e).name() << std::endl;if (e == ParseError::Below) {std::cout << "ParseError::Below" << std::endl;} else if (e == ParseError::Above) {std::cout << "ParseError::Above" << std::endl;} else {std::cout << "ParseError" << std::endl;}return std::unexpected{e};});
}

mingw-gcc 运行效果

[or_else] Type:10ParseError
ParseError::Below
[and_then] Type:NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Sunday
[or_else] Type:10ParseError
ParseError::Above

🎚️transform & transform_error

transform() 如果 *this:

  • 表示预期值,那么调用 f 并返回一个包含预期值的 std::expected 对象,以 f 的结果初始化该值(或在结果类型是 void 时值初始化)。
  • 否则返回一个包含非预期值的 std::expected 对象,以 *this 的非预期值初始化该值。

transform_error() 如果 *this:

  • 包含非预期值,那么以 *this 的非预期值作为实参调用 f 并返回一个包含预期值的 std::expected 对象,以 f 的结果初始化该值。
  • 否则返回一个表示预期值的 std::expected 对象。

这两个基本可以被and_then & or_else取代。

主要区别在于,在成功调用时能保证返回一个std::expected,且依赖于 f 的返回值。

这是少有的在 C++ 中可以天然的允许链式编程的函数。

void test(int d) {auto ex = get_weekDay(d);ex/*** 若存在预期值则返回含有变换后的预期值的 expected,否则返回 expected 本身*/.transform([](const auto& e) -> std::expected<std::string, ParseError> {std::cout << "[transform] Type:" << typeid(e).name() << std::endl;std::cout << e << std::endl;return {e};})/*** 若含有预期值则返回 expected 本身,否则返回含有变换后非预期值的 expected*/.transform_error([](const auto& e) -> std::expected<std::string, ParseError> {std::cout << "[transform_error] Type:" << typeid(e).name() << std::endl;if (e == ParseError::Below) {std::cout << "ParseError::Below" << std::endl;} else if (e == ParseError::Above) {std::cout << "ParseError::Above" << std::endl;} else {std::cout << "ParseError" << std::endl;}return std::unexpected{e};});
}

mingw-gcc 运行效果

[transform_error] Type:10ParseError
ParseError::Below
[transform] Type:NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
Sunday
[transform_error] Type:10ParseError
ParseError::Above

⭐END

最后,如果像更深刻的体会这里的链式效果,建议将上面代码的 and_then & or_else 以相反的顺序调用一遍,会有不一样的效果。

这样可以帮助更好的理解调用的逻辑和设计出更好的代码。

🌟跋

ref:

标准库标头 expected

相关类型:

  • (C++17) any的使用与简单实现
  • (C++17) optional的使用
  • (C++17) variant的使用与union对比
  • (C++17) optional 的 3 种用法

🌟交流方式

⭐交流方式⭐ |C/C++|算法|设计模式|软件架构-CSDN社区

关注我,学习更多C/C++,python,算法,软件工程,计算机知识

B站:

👨‍💻主页:天赐细莲 bilibili

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

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

相关文章

嵌入式系统stm32cube本地安装出现的问题

stm32cube在线安装很慢&#xff0c;本地安装中出现的一个bug stm32cube_fw_f4_v1281安装成功之后&#xff0c;如果想安装stm32cube_fw_f4_v1281会提示stm32cube_fw_f4_v1280未安装。 如果先安装stm32cube_fw_f4_v1280之后&#xff0c;再安装stm32cube_fw_f4_v1281还会提示这个…

算法练习题24——leetcode3296移山所需的最小秒数(二分模拟)

【题目描述】 【代码示例&#xff08;java&#xff09;】 class Solution {// 计算让工人们将山的高度降到0所需的最少时间public long minNumberOfSeconds(int mountainHeight, int[] workerTimes) {long left 0; // 最少时间初始为0long right 0; // 最大时间初始化为0// …

java--面向对象编程(中级部分)

IDE&#xff08;集成开发环境&#xff09; java-----IDE&#xff08;集成开发环境&#xff09;-CSDN博客 包 包的三大作用 区分相同名字的类 当类很多时,可以很好的管理类[看Java API 文档] 控制访问范围 包基本语 package com.hsppedu; 说明: 1. package 关键字,表示打…

Java内存泄漏排查

内存泄漏排查 1. 堆内存快照导出2. 导入内存分析工具 1. 堆内存快照导出 获取 Java 进程 ID Windows&#xff1a;执行 jps 命令&#xff0c;或任务管理器查看&#xff0c;又或者执行 tasklist 命令。 注意&#xff1a;当有多个 Java 进程时&#xff0c;任务管理器或 tasklist |…

C++从入门到起飞之——多态 全方位剖析!

&#x1f308;个人主页&#xff1a;秋风起&#xff0c;再归来~&#x1f525;系列专栏&#xff1a;C从入门到起飞 &#x1f516;克心守己&#xff0c;律己则安 目录 1. 多态的概念 2. 多态的定义及实现 2.1 多态的构成条件 2.1.1 实现多态还有两个必须重要条件&…

BFS解决拓扑排序问题

文章目录 拓扑排序有向无环图&#xff08;DAG图&#xff09;AOV网&#xff08;顶点活动图&#xff09;拓扑排序实现拓扑排序 207. 课程表题目解析算法原理代码实现 LCR 113. 课程表 IILCR 114. 火星词典题目链接算法原理代码实现 拓扑排序 有向无环图&#xff08;DAG图&#x…

科研绘图系列:R语言组合多个图形

文章目录 介绍加载R包画图介绍 通过patchworkR包组合多个ggplot数据图形对象。 加载R包 library(ggplot2) library(patchwork)画图 画图theme_set(theme_bw() +theme(

全面介绍 CSS 属性值计算 —— 掌握它就了解大部分 CSS

CSS 的核心之一就在此&#xff0c;直接影响我们开发中的调试和布局&#xff01;&#xff01;&#xff01; 举个 &#x1f330;&#xff1a;页面上存在一个 h1 元素&#xff0c;不设置任何样式&#xff0c;但是当我们点开 computed 查看&#xff0c;几乎 MDN 上的 CSS 属性都存…

2206. 将数组划分成相等数对(排序/哈希)

目录 一&#xff1a;题目&#xff1a; 二&#xff1a;代码&#xff1a; 三&#xff1a;结果&#xff1a; 一&#xff1a;题目&#xff1a; 给你一个整数数组 nums &#xff0c;它包含 2 * n 个整数。 你需要将 nums 划分成 n 个数对&#xff0c;满足&#xff1a; 每个元素…

Python画笔案例-058 绘制单击画酷炫彩盘

1、绘制单击画酷炫彩盘 通过 python 的turtle 库绘制 单击画酷炫彩盘,如下图: 2、实现代码 绘制单击画酷炫彩盘,以下为实现代码: """单击画酷炫彩盘.py"""from turtle import Turtle # 导入海龟类 from random import randint…

经典大语言模型解读(3):参数量更大、泛化性能更强的生成式模型GPT-2

概述 在GPT-1的基础上&#xff0c;OpenAI提出了包含15亿参数&#xff08;GPT-1参数量的10倍以上&#xff09;的GPT-2模型。该模型在一个更大规模的文本数据集WebText上进行预训练。与GPT-1依赖特定任务上的有监督微调来提升性能不同&#xff0c;GPT-2具备更强的零样本&#xf…

「OC」引用计数(一)

iOS学习 前言自动引用计数引用计数引用计数的思考方式自己生成的对象&#xff0c;自己持有非自己生成的对象&#xff0c;自己也能持有不再需要自己持有的对象时释放无法释放非自己持有的对象 总结 前言 在学习oc时对引用计数略有了解&#xff0c;现在进行系统的学习总结。 自动…

Spring AOP - 配置文件方式实现

目录 AOP基础概念 示例1&#xff1a;模拟在com.text包及子包项下所有类名称以ServiceImpl结尾的类的所有方法执行前、执行后、执行正常后返回值、执行过程中出异常的情况 示例2&#xff1a;统计com.text包及子包项下所有类名称以DaoImpl结尾的类的所有方法执行时长情况 AOP基…

英伟达开源 NVLM 1.0 引领多模态 AI 变革

新闻 NVLM 1.0 是由英伟达&#xff08;Nvidia&#xff09;最新推出的一系列前沿级别的多模态大型语言模型&#xff08;MLLM&#xff09;&#xff0c;这些模型在视觉-语言任务上取得了与领先专有模型&#xff08;例如 GPT-4o&#xff09;和开放访问模型&#xff08;例如 Llama 3…

文件上传、重定向、Gin路由

文件上传 单个文件上传 index.html 文件上传前端页面代码&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head><title>index</title> </head> <body> <form action"/upload" method"post"…

【WPF】桌面程序开发之窗口的用户控件详解

使用Visual Studio开发工具&#xff0c;我们可以编写在Windows系统上运行的桌面应用程序。其中&#xff0c;WPF&#xff08;Windows Presentation Foundation&#xff09;项目是一种常见的选择。然而&#xff0c;对于初学者来说&#xff0c;WPF项目中xaml页面的布局设计可能是一…

基础算法(4)——前缀和

1. 前缀和 题目描述&#xff1a; 解法一&#xff1a;暴力解法 直接模拟实现题目流程即可 时间复杂度为&#xff0c;根据题目给出的条件&#xff0c;肯定会超时 解法二&#xff1a;前缀和&#xff08;适用题型&#xff1a;快速 求出数组中某一个 连续区间 的 和&#xff09;…

车路云一体化大模型数据治理方案

车路云一体化大模型数据治理解决方案 "杭州市发改委已批复了杭州交通投资集团的智能网联汽车“车路云一体化”试点项目。这一批复体现了其对该项目可行性研究报告的肯定&#xff0c;预示着杭州市在智能驾驶领域的进一步发展。" 2024年6月18日&#xff0c;第十一届国…

WGS1984快速度确定平面坐标系UTM分带(快速套表、公式计算、软件范围判定)

之前我们介绍了坐标系3带6带快速确定带号及中央经线&#xff08;快速套表、公式计算、软件范围判定&#xff09;就&#xff0c;讲的是CGCS2000 高斯克吕格的投影坐标系。 那还有我们经常用的WGS1984的平面坐标系一般用什么投影呢? 对于全球全国的比如在线地图使用&#xff1a…

面向未来的算力网络连接发展趋势分析

面向未来的算力网络连接发展特点与实践 AI算力研究&#xff1a;英伟达B200再创算力奇迹&#xff0c;液冷、光模块持续革新 英伟达隆重宣布新一代Blackwell架构&#xff0c;华为对GPU算力需求高达百万片。 英伟达发布的GB200 NVL72 机架级系统内部包括 72 个 Blackwell GPU 和…