CppCon 2015 学习:Simple, Extensible Pattern Matching in C++14

什么是 Pattern Matching(模式匹配)

模式匹配就是一种“描述式”的写法,不需要你手动判断、提取数据,而是直接描述你希望的数据结构是什么样子,系统自动判断并提取。❞

你给的定义拆解:

✴ Instead of explicitly extracting and testing…

传统写法是这样的:

if (shape.type == "circle") {double r = shape.radius;// do something
} else if (shape.type == "rectangle") {double w = shape.width;double h = shape.height;// do something
}

这种方式需要你先判断类型,再显式地提取数据成员。这就是“explicitly extracting and testing”。

Pattern Matching 改写为:

match shape {Circle(r) => { /* use r directly */ },Rectangle(w, h) => { /* use w and h directly */ },
}

直接描述想要的结构,比如一个 Circle(r),系统就会帮你提取 r,而不需要你去“访问属性”。
你也可以把它想象成这样:

正则表达式模式匹配
匹配文本结构匹配数据结构
提取子串提取子字段
(\d+)-(\w+)Rectangle(w, h)
if (x matches pattern)match x { pattern => ... }

总结一句话

模式匹配 = 数据结构的“正则表达式”

它让你声明你想要的数据形状,并在匹配时自动提取内容并处理

这是一个 经典的 C++ switch-case 语句例子,它展示了 在运行时对整型变量 i 进行分支匹配的能力。下面是对这段代码的逐行解释:

原始代码:

switch (i) {case 1:std::cout << "one";break;case 2:std::cout << "two";break;case 3:std::cout << "three";break;default:std::cout << "unknown";
}

代码含义:

  • switch (i):根据变量 i 的值,进入匹配的分支。
  • case 1::如果 i == 1,输出 “one”。
  • case 2::如果 i == 2,输出 “two”。
  • case 3::如果 i == 3,输出 “three”。
  • default::如果不匹配任何 case,输出 “unknown”。

特点:

特性说明
运行时匹配编译时无法确定分支走向,必须等 i 的值在运行时才知道。
整型值支持传统 switch 只支持 intenum 类型。
手动 break每个分支后需要加 break 防止“贯穿执行”到下一个 case。
default 备选default 分支相当于“else”逻辑。

类比模式匹配(Pattern Matching)

switch 是一种最基础的“模式匹配”形式,但功能非常有限:

特性switch模式匹配(如 Rust)
支持数据结构仅支持整数值匹配支持结构体/枚举/元组等
自动提取字段不能自动解构(如 Point(x, y)
表达式形式语句形式,不能直接赋值可作为表达式返回值

这段 Haskell 代码是关于 模式匹配(Pattern Matching)元组 / 列表的分解式函数定义,下面是对每一部分的详细解释和理解:

一、函数定义:提取三元组中的元素

first :: (a, b, c) -> a
first (x, _, _) = x
  • 类型签名 :: (a, b, c) -> a 表示:函数 first 接收一个三元组 (a, b, c),返回其中的第一个元素 a
  • (x, _, _) = x 使用模式匹配提取第一个值,忽略其他两个(用 _ 表示不关心)。
    类似的:
second :: (a, b, c) -> b
second (_, y, _) = y
third :: (a, b, c) -> c
third (_, _, z) = z

这些函数从三元组中提取第二、第三个元素。

二、列表分析函数 describeList

describeList :: [a] -> String
describeList xs = "The list is " ++ case xs of[]   -> "empty."[x]  -> "a singleton list."xs   -> "a longer list."
类型说明:
  • :: [a] -> String 表示该函数接收一个任意类型元素的列表,返回一个 String 描述。
逻辑说明:
  • case xs of 使用 模式匹配 来分析 xs 的结构:
    模式匹配条件返回文本
    []空列表"empty."
    [x]只包含一个元素的列表"a singleton list."
    xs(默认)多于一个元素的列表"a longer list."
示例:
describeList []         -- "The list is empty."
describeList [42]       -- "The list is a singleton list."
describeList [1,2,3]    -- "The list is a longer list."

三、总结

概念说明
模式匹配(Pattern Matching)Haskell 的核心特性,可在函数参数、case 表达式中直接分解数据结构。
元组分解(x, _, _) 形式表示从三元组中提取出想要的元素。
列表匹配[], [x], xs 等用于分别匹配空列表、单元素列表、多元素列表。
表达式匹配 + 拼接使用 ++ 拼接字符串,用 case 对输入做结构匹配判断并产生不同返回值。

你给出的这段代码是 Rust 中 模式匹配(match 的典型用法。下面是对它的完整解释:

代码回顾

let x = 1;
match x {1 | 2 => println!("one or two"), 3 => println!("three"),_ => println!("anything"), 
}

逐行解释

let x = 1;

  • 这行代码定义了一个变量 x,它的值为 1

match x { ... }

这是 Rust 中的 模式匹配结构,类似于其他语言中的 switch,但更强大。
Rust 的 match 表达式根据变量的值与不同的 模式(patterns) 进行匹配,一旦匹配成功,就执行对应的代码块。

分支解释:

1 | 2 => println!("one or two"),
  • 1 | 2 表示:如果 x 是 1 或 2,就执行这一分支。
  • | 是逻辑“或”的模式匹配用法(不是布尔操作)。
3 => println!("three"),
  • x == 3 时匹配这个分支。
_ => println!("anything"),
  • _ 是通配符,表示“其他任何情况”。
  • 如果 x 不是 1、2 或 3,就会匹配这个分支。

本例中运行结果

由于 x = 1,因此匹配第一个分支:

one or two

总结

结构说明
match用于模式匹配变量的值
``匹配多个值中的任一个
_匹配所有未被显式列出的情况
=>分支体开始

小技巧

  • match 在 Rust 中是表达式(expression),所以它可以返回值。
  • 分支是穷尽性匹配,编译器会强制你覆盖所有可能性,或使用 _ 兜底。
  • match 也可以解构结构体、枚举、元组、引用等,功能非常强大。

这段 Rust 代码展示了 模式匹配(pattern matching) 在元组(tuple)上的用法。我们来逐步理解它:

原始代码

let tup = (1, 0);
match tup {(0, 0) => println!("both zero"),(x, 0) => println!("{} and zero", x),(0, y) => println!("zero and {}", y),_      => println!("did not match"),
}

变量定义

let tup = (1, 0);
  • 创建了一个元组变量 tup,其值是 (1, 0)

match 分支解析

Rust 的 match 会从上到下尝试匹配每个模式:

(0, 0) => println!("both zero")

  • 匹配元组两个元素都是 0 的情况。
  • 当前是 (1, 0)不匹配

(x, 0) => println!("{} and zero", x)

  • 匹配元组第二个元素为 0,第一个元素任意(绑定为 x)。
  • 当前是 (1, 0)匹配成功
  • 执行:println!("{} and zero", x),输出:
1 and zero

匹配成功后,match 结构结束,不会继续匹配下面的分支。

(0, y) => println!("zero and {}", y)

  • 匹配第一个是 0,第二个任意的元组。
  • 当前不匹配,因此不会执行。

_ => println!("did not match")

  • _ 是通配符:匹配所有未匹配到的情况。
  • 本例中没走到这一分支。

运行结果

1 and zero

小结

模式含义匹配 (1, 0) 吗?
(0, 0)两个都是 0
(x, 0)第二个是 0,第一个绑定为 x
(0, y)第一个是 0,第二个绑定为 y
_其他任何情况(兜底)不会执行
如果你想学习更多 Rust 中的模式匹配技巧,例如:
  • 匹配结构体和枚举
  • 使用 match guard(例如 if x > 0
  • 模式绑定的细节(如 @ 绑定)

这段 Rust 代码展示了如何使用 枚举(enum)和模式匹配(match 来处理不同类型的消息(Message)。我们来逐步分析和理解它:

枚举定义

enum Message {Quit,ChangeColor(i32, i32, i32),Move { x: i32, y: i32 },Write(String),
}

这定义了一个 Message 类型,它有 4 种变体(variants):

变体名类型描述
Quit无数据退出指令
ChangeColor包含三个 i32 参数改变颜色(RGB)
Move是一个具名结构体样式的变体移动到 (x, y) 坐标位置
Write包含一个 String输出字符串

process_message 函数

fn process_message(msg: Message) {match msg {Message::Quit => quit(),Message::ChangeColor(r, g, b) => change_color(r, g, b),Message::Move { x: x, y: y } => move_cursor(x, y),Message::Write(s) => println!("{}", s),};
}

该函数接收一个 Message 类型的参数,然后使用 match 匹配它是哪种变体,并执行相应的操作。

逐个分支解释

1. Message::Quit => quit()
  • 如果是 Quit 变体,调用 quit() 函数。
  • 不包含任何数据。
2. Message::ChangeColor(r, g, b) => change_color(r, g, b)
  • 如果是 ChangeColor,提取出三个整数,绑定为 r, g, b,然后传给 change_color 函数。
  • 这是 位置匹配(positional matching)
3. Message::Move { x: x, y: y } => move_cursor(x, y)
  • 如果是 Move 变体,它是具名字段结构体形式。
  • 提取 xy 字段,传入 move_cursor(x, y)
  • 可以简写为 { x, y } 而不是 { x: x, y: y }
4. Message::Write(s) => println!("{}", s)
  • 如果是 Write(String),提取出字符串 s,并打印。

简写优化(推荐写法)

你可以把 x: x, y: y 简写为 x, y

Message::Move { x, y } => move_cursor(x, y)

示例调用

process_message(Message::Quit);
process_message(Message::Write("Hello!".to_string()));
process_message(Message::Move { x: 10, y: 20 });
process_message(Message::ChangeColor(255, 0, 0));

小结

这个例子体现了 Rust 的模式匹配能力:

  • 适用于结构体、枚举、元组等
  • 自动解构并绑定变量
  • 简洁且类型安全
    如果你来自其他语言(如 C++、Java),可以把这理解为:
  • enum 是 tagged union + 类型安全
  • match 类似 switch,但更强大,可解构结构体和元组

后面应该是介绍这个c++怎么实现的看不懂 知道模式匹配这个东西就行

https://github.com/jbandela/simple_match

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

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

相关文章

刷题记录(7)二叉树

一、单值二叉树 二叉树为二叉链表形式&#xff0c;结点为&#xff1a; 大概看看题就知道这道题让我们判断一个树到底所有结点的值是不是相同&#xff0c;相同就是单值二叉树。在实现二叉树相关操作的时候已经体会到了&#xff0c;递归来遍历二叉树是非常舒服的&#xff08;做这…

开源:FTP同步工具

文章目录 简介功能特性Windows (EXE)从源代码构建依赖项Linux 构建Windows 构建 使用方法软件截图主界面FTP 设置快捷菜单定时设置 配置说明开发与贡献许可证 欢迎来到盹猫的博客 本篇文章主要介绍了 [开源:FTP同步工具] ❤博主广交技术好友&#xff0c;喜欢我的文章的可以关注…

视频质量测试点

目录 功能/UI 端侧性能 媒体质量 主观 客观 稳定性 兼容性 功能/UI 视频预览音频预览音视频同步全屏收藏打赏 端侧性能 PC端&#xff1a;内存占用、网络带宽占用等&#xff1b; 移动端&#xff1a;内存占用、功耗、发热、流量消耗等&#xff1b; 媒体质量 主观 音…

Ray框架:分布式AI训练与调参实践

Ray框架&#xff1a;分布式AI训练与调参实践 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 Ray框架&#xff1a;分布式AI训练与调参实践摘要引言框架架构解析1. 核心组件设计2. 关键技术实现2.1 动态资源调度2.2 …

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…

ubuntu22.04 安装docker 和docker-compose

首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题

20250609在荣品的PRO-RK3566开发板的Android13下解决串口可以执行命令但是脚本执行命令异常的问题 2025/6/9 20:54 缘起&#xff0c;为了跨网段推流&#xff0c;千辛万苦配置好了网络参数。 但是命令iptables -t filter -F tetherctrl_FORWARD可以在调试串口/DEBUG口正确执行。…

【C/C++】高效的位操作

位运算&#xff08;Bitwise Operation&#xff09;是直接对整数的二进制位进行操作的运算方式&#xff0c;在底层开发、性能优化、算法设计中广泛使用。 1 基本位运算符及含义 运算符名称示例&#xff08;a5, b3&#xff09;运算过程&#xff08;二进制&#xff09;结果&按…

后端下载限速(redis记录实时并发,bucket4j动态限速)

✅ 使用 Redis 记录 所有用户的实时并发下载数✅ 使用 Bucket4j 实现 全局下载速率限制&#xff08;动态&#xff09;✅ 支持 动态调整限速策略✅ 下载接口安全、稳定、可监控 &#x1f9e9; 整体架构概览 模块功能Redis存储全局并发数和带宽令牌桶状态Bucket4j Redis分布式限…

android app 一个 crash的解决过程!

一、日志&#xff1a; crash 2024-10-25 12:15:33.020 2113-2113 AndroidRuntime pid-2113 E FATAL EXCEPTION: main Process: com..workhome, PID: 2113 java.lang.RuntimeException: Unable to start activity ComponentInfo{com..w…

[Java 基础]Object 类

java.lang.Object 是 Java 所有类的直接或间接父类&#xff0c;Java 中每个类都默认继承 Object 类&#xff08;即使你没写 extends Object&#xff09;。 Object 中的常用方法&#xff1a; 方法名功能简介toString()返回对象的字符串表示equals(Object)判断两个对象是否“逻…

大数据学习(135)-Linux系统性指令

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…

【Fifty Project - D35】

今日完成记录 TimePlan完成情况7&#xff1a;00 - 7&#xff1a;40爬坡√8&#xff1a;30 - 11&#xff1a;30Rabbit MQ√17&#xff1a;30 - 18&#xff1a;30羽毛球√ RabbitMQ 消费者端如何保证可靠性&#xff1f; 消息投递过程出现网络故障消费者接收到消息但是突然宕机…

P3 QT项目----记事本(3.4)

3.4 文件选择对话框 QFileDialog 3.4.1 QFileDialog 开发流程 使用 QFileDialog 的基本步骤通常如下&#xff1a; 实例化 &#xff1a;首先&#xff0c;创建一个 QFileDialog 对象的实例。 QFileDialog qFileDialog;设置模式 &#xff1a;根据需要设置对话框的模式&…

学习笔记(26):线性代数-张量的降维求和,简单示例

学习笔记(26)&#xff1a;线性代数-张量的降维求和&#xff0c;简单示例 1.先理解 “轴&#xff08;Axis&#xff09;” 的含义 张量的 “轴” 可以理解为 维度的方向索引 。对于形状为 (2, 3, 4) 的张量&#xff0c;3 个轴的含义是&#xff1a; 轴 0&#xff08;axis0&…

健康档案实训室:构建全周期健康管理的数据基石

一、健康档案实训室建设背景 随着“健康中国2030”战略深入推进&#xff0c;健康档案作为居民健康数据的核心载体&#xff0c;在疾病预防、慢性病管理、医疗决策等领域的价值日益凸显。在此背景下&#xff0c;健康档案实训室建设成为职业院校对接政策要求、培养专业健康管理…

【MATLAB第119期】基于MATLAB的KRR多输入多输出全局敏感性分析模型运用(无目标函数,考虑代理模型)

【MATLAB第119期】基于MATLAB的KRR多输入多输出全局敏感性分析模型运用&#xff08;无目标函数&#xff0c;考虑代理模型&#xff09; 下一期研究SHAP的多输入多输出敏感性分析方法 一、SOBOL&#xff08;无目标函数&#xff09; &#xff08;1&#xff09;针对简单线性数据…

Linux常用文件目录命令

浏览目录命令&#xff1a; ls 、pwd目录操作命令&#xff1a;cd、mkdir、rmdir浏览文件命令&#xff1a;cat、more、less、head、tail文件操作命令&#xff1a;cp、rm、mv、find、grep、tar 浏览目录命令 ls ◼ 命令名称&#xff1a;ls ◼ 命令英文原意&#xff1a;list ◼ …

PIN码vs密码,电脑登录的快捷键你用对了吗?

你是否也遇到过这样的窘境&#xff1a;信心满满地输入电脑开机密码&#xff0c;屏幕却无情地提示“密码错误”。仔细一看&#xff0c;才发现登录界面悄悄地变成了要求输入“PIN码”。这种因为混淆了PIN码和账户密码而导致的开机失败&#xff0c;相信不少朋友都碰到过。 PIN码作…