如何制作一个所有字段都是公共的公共结构而不为每个字段重复“pub”?

Posted

技术标签:

【中文标题】如何制作一个所有字段都是公共的公共结构而不为每个字段重复“pub”?【英文标题】:How to make a public struct where all fields are public without repeating `pub` for every field? 【发布时间】:2019-05-20 20:19:59 【问题描述】:

如何在 Rust 中定义一个公共结构,其中所有字段都是公共的,而不必在每个字段前重复 pub 修饰符?

pub_struct 宏将是理想的:

pub_struct! Foo 
    a: i32,
    b: f64,
    // ...

相当于:

pub struct Foo 
    pub a: i32,
    pub b: f64,
    //...

【问题讨论】:

让我们明确一点:你想要一个没有第一列精确的结构声明 public ?宏可能可以插入这些修饰符,但您代码的其他读者必须学习您自己的特殊语法才能理解整个是公共的...... 所以pub Foo pub a: u32, pub b: u32 不是您要找的? 你解决了错误的问题。只需在每个字段前面写上pub 即可。重复代码是不好的,因为以后对代码的更改很容易出错——你可能会错过其中一个重复。这不是在每个字段名称前写pub 的问题。即使您决定稍后更改此设置,也几乎没有出错的风险。 @PetrusTheron,编写这样的派生可能是一个板条箱大小的工作。要获得有关生成此类方法的灵感,您可以查看getset crate,它能够为您生成公共 getter 和 setter。 @PetrusTheron 您可以在编辑器中使用多个光标或键盘宏来轻松地在每行前面添加pub,我认为这是正确的解决方案。在这里使用宏会使代码库的新手更难阅读代码,我相信这就是人们投票反对的原因。如果你决定无论如何都要使用宏,你可以从(struct $name:ident $($field:ident : $type:ty,)* ) => pub struct $name $(pub $field: $type,)* 之类的规则开始,并根据需要对其进行细化以支持通用参数和字段属性。 【参考方案1】:
macro_rules! pub_struct 
    ($name:ident $($field:ident: $t:ty,)*) => 
        #[derive(Debug, Clone, PartialEq)] // ewww
        pub struct $name 
            $(pub $field: $t),*
        
    

不幸的是,derive 可能只应用于结构、枚举和联合,所以我不知道如何将它们提升给调用者。

用法:

pub_struct!(Foo 
    a: i32,
    b: f64,
);

如果我不需要括号和分号就好了,即如果 Rust 支持阅读器宏。

【讨论】:

Rust's API guidelines recommend including the struct keyword in the macro syntax。这也将允许cleaner handling of the derive macros。 @SvenMarnach 所以可能类似于pub! struct a: i32, ...? 我不认为这是可能的 - 宏名称后必须有某种开头的分隔符。 @SvenMarnach 你可以删除derive 的硬编码。见Generating documentation in macros @SvenMarnach 对...这就是我读到的内容,它硬编码了 derive 这个词。我指出你不需要这样做。此外,您扩展宏以支持 any 属性。

以上是关于如何制作一个所有字段都是公共的公共结构而不为每个字段重复“pub”?的主要内容,如果未能解决你的问题,请参考以下文章

CodeSmith公共类维护

插件中不存在公共功能

如何在 ES6 类中创建“公共静态字段”?

“公共结构包含一个或多个将被导出的非公共字段” - 但是没有字段?

如何制作只能在库中看到的目标 c 方法,而不是在导出的标头中

如何定义游标,当我们在两个表之间有一个公共列而不给出别名时