簡體   English   中英

自動創建枚舉變體

[英]Automatically create enum variants

我想要的宏會自動將帶有屬性宏的結構添加到枚舉中。 例如

#[add_enum(AutoEnum)]
struct A(usize);
#[add_enum(AutoEnum)]
struct B(i32);

#[auto_enum]
enum AutoEnum{}

展開以上內容

struct A(usize);
struct B(i32);

enum AutoEnum{
  A(A),
  B(B),
}

我環顧四周,找不到獲取有關其他屬性宏的信息的方法(例如#[add_enum(AutoEnum)]來自#[auto_enum] )。

這可能嗎?

這是一個瘋狂的想法,它可能在您的真實代碼中不起作用,但應該在您給出的示例中起作用(在稍作修改后)。

與 Rust 中的所有其他項目相反,宏可以相互遮蔽。 如果你有兩個同名的宏,后面定義的宏將覆蓋第一個宏。

所以,我認為...如果我們為枚舉變體的所有可能名稱定義宏,然后為每個實際枚舉隱藏它們呢? 這將為我們提供一種方法來將每個變體擴展到我們想要的。

舉個例子會更清楚。 假設我們只想支持字母 AC 作為變體名稱,並且只支持一個字母(沒有AC )。 我們首先需要一些地方來定義“默認”無變體宏,它需要在任何變體之前。 所以讓我們修改示例如下:

#[auto_enum(declare)] // New!
enum AutoEnum {}

#[add_enum(AutoEnum)]
struct A(usize);
#[add_enum(AutoEnum)]
struct B(i32);

#[auto_enum(define)] // Changed! (This is not necessary).
enum AutoEnum {}

然后, #[auto_enum(declare)]將擴展為以下三個“默認”宏,將它們的輸入按原樣傳遞給下一個宏,除了創建最終枚舉的最后一個宏:

macro_rules! AutoEnum_A {
    ( $($t:tt)* ) => { AutoEnum_B! { $($t)* } };
}
macro_rules! AutoEnum_B {
    ( $($t:tt)* ) => { AutoEnum_C! { $($t)* } };
}
macro_rules! AutoEnum_C {
    ( $($t:tt)* ) => {
        enum AutoEnum { $($t)* }
    };
}

現在,每個#[add_enum]調用都將擴展為一個隱藏“默認”宏的宏,而不是按原樣將輸入傳遞給下一個宏,而是將其變體添加到其中:

// #[add_enum(AutoEnum)]
// struct A(usize);
macro_rules! AutoEnum_A {
    ( $($t:tt)* ) => { AutoEnum_B! { $($t)* A(usize), } };
}
// #[add_enum(AutoEnum)]
// struct B(i32);
macro_rules! AutoEnum_B {
    ( $($t:tt)* ) => { AutoEnum_C! { $($t)* B(i32), } };
}

最后, #[auto_enum(define)]將擴展為對第一個宏的調用,最終在鏈末尾的調用將生成枚舉:

AutoEnum_A! {}

當然,對於每個字母(假設你要支持大寫/小寫/數字/下划線)這需要 63 種組合,這意味着即使支持 5 個字母也需要 992436543 個宏,所以這並不是真正可用的。 但仍然是一個值得探索的有趣想法。

我仍在尋找更好的想法,希望這些想法也可用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM