当前位置: 首页 > news >正文

Rust derive macro(Rust #[derive])Rust派生宏

参考文章:附录 D:派生特征 trait

文章目录

  • Rust 中的派生宏 #[derive]
    • 基础使用
      • 示例:派生 `Debug`
    • 派生其他常用特征
      • 示例:派生 `Clone` 和 `Copy`
    • 派生宏的限制和自定义派生
      • 自定义派生宏
        • 上面代码运行时报错了,以下是解释
    • 结论

Rust 中的派生宏 #[derive]

在 Rust 中,派生宏(derive macro)是一种自动实现特定特征(trait)的工具,极大地简化了代码的编写和维护过程。通过使用 #[derive] 属性,开发者可以轻松为自定义数据类型实现一系列的标准特征,例如 DebugCloneCopyHashPartialEqEq 等。本文将深入探讨派生宏的工作原理、使用方式以及如何自定义派生宏。

基础使用

派生宏最常见的应用是自动实现标准库中的特征。例如,当你需要打印一个结构体的调试信息时,可以派生 Debug 特征。

示例:派生 Debug

#![allow(dead_code)] // 忽略全局dead code,放在模块开头!
#![allow(unused_variables)] // 忽略未使用变量,放在模块开头!#[derive(Debug)]struct Point {x: i32,y: i32,
}fn main() {let point = Point { x: 10, y: 20 };println!("{:?}", point); // 使用 Debug 特征打印 point
}

在这里插入图片描述

在上述代码中,#[derive(Debug)] 使得 Point 结构体自动实现了 Debug 特征,允许我们通过 println! 宏以调试格式打印结构体的实例。

派生其他常用特征

除了 Debug,Rust 还允许自动派生其他一些重要的特征。

示例:派生 CloneCopy

#![allow(dead_code)] // 忽略全局dead code,放在模块开头!
#![allow(unused_variables)] // 忽略未使用变量,放在模块开头!#[derive(Debug, Clone, Copy)]struct Point {x: i32,y: i32,
}fn main() {let point1 = Point { x: 10, y: 20 };let point2 = point1; // Copy 特性允许这样的操作let point3 = point1.clone(); // Clone 特性的显式调用println!("{:?}", point2); // 使用 Debug 特征打印 point2println!("{:?}", point3); // 使用 Debug 特征打印 point3
}

在这里插入图片描述

在此示例中,Point 结构体通过 #[derive] 同时实现了 DebugCloneCopy 特征。Copy 是用于简单字段复制的轻量级特征,而 Clone 用于可能涉及到更复杂的数据克隆过程。

派生宏的限制和自定义派生

尽管派生宏非常有用,但它们并不适用于所有情况。例如,当结构体的某些字段不支持相应的特征时,直接使用派生宏可能会导致编译错误。

自定义派生宏

对于标准特征之外的特定用途,或当内置的派生无法满足需求时,Rust 允许创建自定义派生宏。自定义派生宏需要深入了解 Rust 的宏系统和特征实现。

use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, DeriveInput};#[proc_macro_derive(MyTrait)]
pub fn my_trait_derive(input: TokenStream) -> TokenStream {let input = parse_macro_input!(input as DeriveInput);let name = &input.ident;let expanded = quote! {impl MyTrait for #name {fn my_trait_method(&self) -> String {format!("This is a MyTrait method implemented for {}", stringify!(#name))}}};TokenStream::from(expanded)
}

在上述示例中,定义了一个新的派生宏 MyTrait,它为指定的数据类型实现了 MyTrait 特征,包括一个方法 my_trait_method。使用 proc_macro 创建派生宏涉及解析类型定义、生成相应的代码,并将其输出为令牌流,这是 Rust 宏系统的核心。

上面代码运行时报错了,以下是解释

在 Rust 中,#[proc_macro_derive] 属性只能在 proc-macro 类型的 crate 中使用。这意味着你需要将你的代码放在一个特别设定为 proc-macro 类型的库中才能编译和运行。以下是设置步骤:

  1. 创建新的 proc-macro crate

    • 通常,你需要创建一个新的库专门用来编写 proc macro。你可以使用 cargo new --lib my_proc_macro 命令来创建一个新的库。确保你在创建时的目录不在其他项目中。
  2. 修改 Cargo.toml

    • 在你的 Cargo.toml 文件中,你需要指定库的类型为 proc-macro。这可以通过添加 proc-macro = true[lib] 部分实现:
      [lib]
      proc-macro = true
      
  3. 将代码移动到新的 crate

    • 把你的 proc macro 代码复制到新创建的库的 src/lib.rs 文件中。
  4. 添加依赖

    • 你需要在 Cargo.toml 中添加 proc_macro, quote, 和 syn 作为依赖项。这样你的代码才能编译。
      [dependencies]
      quote = "1.0"
      syn = { version = "1.0", features = ["full"] }
      
  5. 编译并使用你的 proc-macro crate

    • 在你的主项目中,添加对你刚创建的 proc-macro 库的依赖。这通常通过在主项目的 Cargo.toml 中添加路径依赖来实现:
      [dependencies]
      my_proc_macro = { path = "../path_to_my_proc_macro" }
      
  6. 使用 proc-macro

    • 现在,你可以在你的主项目中通过使用 #[derive(MyTrait)] 来使用你的 proc macro。

确保你的目录结构和依赖管理都设置正确,这样你就可以成功地编译和使用你的 proc macro。如果你需要进一步的帮助,可以随时提问!

结论

Rust 的 #[derive] 宏提供了一种高效的方式来自动实现多种特征,从而减少重复代码并提升开发效率。通过自定义派生宏,开发者还可以扩展这一机制以适应更广泛的应用场景。

相关文章:

Rust derive macro(Rust #[derive])Rust派生宏

参考文章:附录 D:派生特征 trait 文章目录 Rust 中的派生宏 #[derive]基础使用示例:派生 Debug 派生其他常用特征示例:派生 Clone 和 Copy 派生宏的限制和自定义派生自定义派生宏上面代码运行时报错了,以下是解释 结论…...

springboot嗨玩旅游网站

摘 要 嗨玩旅游网站是一个专为旅行爱好者打造的在线平台。我们提供丰富多样的旅游目的地信息,包括景点信息、旅游线路、商品信息、社区信息、活动推广等,帮助用户轻松规划行程。嗨玩旅游网站致力于为用户提供便捷、实用的旅行服务,让每一次旅…...

杰发科技AC7840——EEP中RAM的配置

sample和手册中示例代码的sram区地址定义不一样 这个在RAM中使用没有限制,根据这个表格留下足够空间即可 比如需要4096字节的eep空间,可以把RAM的地址改成E000,即E000-EFFF,共4096bytes即可。...

从零开始的c++之旅——map_set的使用

1.序列式容器和关联式容器 序列式容器:逻辑结构为线性序列的数据结构,两个位置之间没有紧密的关系,比如两者交换一下还是序列式的容器,例如string,vector,deque,array等。 关联式容器&#xff1…...

Docker中的一些常用命令

find / -type f -name “文件名” 2>/dev/null 寻找所有目录中的这个文件 pwd 查看当前目录的地址 docker pull 镜像名 强制拉镜像 docker run 运行docker systemctl daemon-reload 关闭docker systemctl start docker 启动docker systemctl restart docker 重启docker /…...

自存 sql常见语句和实际应用

关于连表 查询两个表 SELECT * FROM study_article JOIN study_article_review 查询的就是两个表相乘,结果为两个表的笛卡尔积 相这样 这种并不是我们想要的结果 通常会添加一些查询条件 SELECT * FROM study_articleJOIN study_article_review ON study_art…...

python | argparse模块在命令行的使用中的重要作用

import argparseclass TestCases:def __init__(self, nameNone, expect_resultNone):self.name nameself.expect expect_resultself.parser argparse.ArgumentParser() # 创建命令解析器self.add_arguments() # 方法 : 添加命令self.args, _ self.parser.par…...

【HCIP]——OSPF综合实验

题目 实验需求 根据上图可得,实验需求为: 1.R5作为ISP:其上只能配置IP地址;R4作为企业边界路由器,出口公网地址需要通过PPP协议获取,并进行CHAP认证。(PS:因PPP协议尚未学习&#…...

PW系列工控电脑复制机:效率与精度双重提升

工控电脑复制应用:效率与精度的双重提升 随着现代企业对大数据、数据备份、和跨平台兼容性需求的快速增长,工控电脑已成为数据密集型产业的核心设备。针对工控环境中大量数据复制的特殊需求,PW系列NVMe/SATA PCIe SSD复制机(如PW…...

学习QT第二天

QT6示例运行 运行一个Widgets程序运行一个QT Quick示例 工作太忙了,难得抽空学点东西。-_-||| 博客中有错误的地方,请各位道友及时指正,感谢! 运行一个Widgets程序 在QT Creator的欢迎界面中,点击左侧的示例&#xf…...

11.20作业

题目一&#xff1a; 题目&#xff1a; // 数组的行列转置 代码&#xff1a; // 数组的行列转置 #include <stdio.h> int main() {int a[2][3], i, j, b[3][2];printf("输入一个两行三列的数组a:\n");for (i 0; i < 2; i)for (j 0; j < 3; j){scanf…...

Ubuntu Linux使用前准备动作_使用root登录图形化界面

Ubuntu默认是不允许使用 root 登录图形化界面的。这是出于安全考虑的设置。但如果有需要&#xff0c;可以通过以下步骤来实现使用 root 登录&#xff1a; 1、设置 root 密码 打开终端&#xff0c;使用当前的管理员账户登录系统。在终端中输入命令sudo passwd root&#xff0c…...

DICOM核心概念:显式 VR(Explicit VR)与隐式 VR(Implicit VR)在DICOM中的定义与区别

在DICOM&#xff08;Digital Imaging and Communications in Medicine&#xff09;标准中&#xff0c;VR&#xff08;Value Representation&#xff09; 表示数据元素的值的类型和格式。理解显式 VR&#xff08;Explicit VR&#xff09;与隐式 VR&#xff08;Implicit VR&#…...

源码分析Spring Boot (v3.3.0)

. ____ _ __ _ _/\\ / ____ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | _ | _| | _ \/ _ | \ \ \ \\\/ ___)| |_)| | | | | || (_| | ) ) ) ) |____| .__|_| |_|_| |_\__, | / / / /|_||___//_/_/_/:: Spring Boot :: (v3.3.0)//笔记背…...

IPv6 NDP 记录

NDP&#xff08;Neighbor Discovery Protocol&#xff0c;邻居发现协议&#xff09; 是 IPv6 的一个关键协议&#xff0c;它组合了 IPv4 中的 ARP、ICMP 路由器发现和 ICMP 重定向等协议&#xff0c;并对它们作出了改进。该协议使用 ICMPv6 协议实现&#xff0c;作为 IPv6 的基…...

linux常用命令(文件操作)

目录 1. ls - 列出目录内容 2. cd - 更改目录 3. pwd - 打印当前工作目录 4. mkdir - 创建目录 5. rm - 删除文件或目录 6. cp - 复制文件或目录 7. mv - 移动或重命名文件 8. touch - 更新文件访问和修改时间 9. cat - 显示文件内容 10. grep - 搜索文本 11. chmod…...

内存管理 I(内存管理的基本原理和要求、连续分配管理方式)

一、内存管理的基本原理和要求 内存管理&#xff08;Memory Management&#xff09;是操作系统设计中最重要和最复杂的内容之一。虽然计算机硬件技术一直在飞速发展&#xff0c;内存容量也在不断增大&#xff0c;但仍然不可能将所有用户进程和系统所需要的全部程序与数据放入主…...

【Redis】基于Redis实现秒杀功能

业务的流程大概就是&#xff0c;先判断优惠卷是否过期&#xff0c;然后判断是否有库存&#xff0c;最好进行扣减库存&#xff0c;加入全局唯一id&#xff0c;然后生成订单。 一、超卖问题 真是的场景下可能会有超卖问题&#xff0c;比如开200个线程进行抢购&#xff0c;抢100个…...

Hadoop 使用过程中 15 个常见问题的详细描述、解决方案

目录 问题 1&#xff1a;配置文件路径错误问题描述解决方案Python 实现 问题 2&#xff1a;YARN 资源配置不足问题描述解决方案Python 实现 问题 3&#xff1a;DataNode 无法启动问题描述解决方案Python 实现 问题 4&#xff1a;NameNode 格式化失败问题描述解决方案Python 实现…...

【Flutter 问题系列第 84 篇】如何清除指定网络图片的缓存

这是【Flutter 问题系列第 84 篇】&#xff0c;如果觉得有用的话&#xff0c;欢迎关注专栏。 博文当前所用 Flutter SDK&#xff1a;3.24.3、Dart SDK&#xff1a;3.5.3&#xff0c;网络图片缓存用的插件 cached_network_image: 3.4.1&#xff0c;缓存的网络图像的存储和检索用…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

dify打造数据可视化图表

一、概述 在日常工作和学习中&#xff0c;我们经常需要和数据打交道。无论是分析报告、项目展示&#xff0c;还是简单的数据洞察&#xff0c;一个清晰直观的图表&#xff0c;往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server&#xff0c;由蚂蚁集团 AntV 团队…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

【生成模型】视频生成论文调研

工作清单 上游应用方向&#xff1a;控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...