如何获取宏重复单个元素的索引

问题描述 投票:0回答:2

我需要获取宏重复元素的索引来编写下一个代码:

struct A {
    data: [i32; 3]
}

macro_rules! tst {
    ( $( $n:ident ),* ) => {
        impl A {
            $(
                fn $n(self) -> i32 {
                    self.data[?] // here I need the index
                }
            )*
        }
    }
}

我知道一种方法:只需告诉用户用手写索引:

( $( $i:ident => $n:ident ),* )

但是有没有更优雅的方式不需要用户操作?

macros rust
2个回答
16
投票

最简单的方法是使用递归,如下所示:

struct A {
    data: [i32; 3]
}

macro_rules! tst {
    (@step $_idx:expr,) => {};

    (@step $idx:expr, $head:ident, $($tail:ident,)*) => {
        impl A {
            fn $head(&self) -> i32 {
                self.data[$idx]
            }
        }

        tst!(@step $idx + 1usize, $($tail,)*);
    };

    ($($n:ident),*) => {
        tst!(@step 0usize, $($n,)*);
    }
}

tst!(one, two, three);

fn main() {
    let a = A { data: [10, 20, 30] };
    println!("{:?}", (a.one(), a.two(), a.three()));
}

请注意,我更改了方法以采用

&self
而不是
self
,因为这样可以更轻松地在
main
函数中编写示例。 :)

递归中的每一步只是将索引加 1。使用“类型化”整数文字是一个好主意,以避免由于大量整数推断而导致编译速度减慢。


0
投票

希望当RFC:声明性宏元变量表达式#3086完全实现时,这最终将变得可用。现在您必须启用

macro_metavar_expr
:

#![feature(macro_metavar_expr)]
macro_rules! tst {
    ( $( $n:ident ),* ) => {
        impl A {
            $(
                fn $n(self) -> i32 {
                    self.data[${index()}]
                }
            )*
        }
    }
}

tst!(x, y, z);
© www.soinside.com 2019 - 2024. All rights reserved.