Rust 如何编写基于字符串返回结构的实现方法的宏?

Rust 如何编写基于字符串返回结构的实现方法的宏?,rust,macros,rust-macros,Rust,Macros,Rust Macros,受此启发,我想获得一个基于str的结构实现方法,类似于: macro_rules! comp { (struct $name:ident { $($field_name:ident : $field_type:ty,)* } impl $name2:ident { $(pub fn $func_name:ident($($args:tt)*) $bk:block)* } ) => { //basic

受此启发,我想获得一个基于
str
的结构实现方法,类似于:

macro_rules! comp {
    (struct $name:ident {
        $($field_name:ident : $field_type:ty,)*
    }
    impl $name2:ident {
        $(pub fn $func_name:ident($($args:tt)*) $bk:block)*
    }

    ) => {
        //basic component
        struct $name {
            $($field_name: $field_type),*
        }
        impl $name {
            $(pub fn $func_name($($args)*) $bk)*

            // the generated function
            pub fn get_method(index: &str) -> &'static dyn Fn() {
                $(if stringify!($func_name) == index {
                    return $func_name;                               // (***)
                })*
                //
                // Some code here to return the right function
                //
            }
        }
    };
}

fn main() {
    comp! {
        struct S {
            field: String,
        }
         impl S {
            pub fn method1() {
                println!("method1 called");
            }
            pub fn method2() {
                println!("method2 called");
            }
        }
    }
    // the functionality should achieved
    // S::get_method("method1") == S::method1
    // S::get_method("method2") == S::method2
}
最初我想用
返回$func_name
获取函数指针,但似乎不可能;标有
(***)
的代码行获取错误:

错误[E0423]:应为函数,找到宏“stringify”`
-->src/main.rs:19:22
|
19 |$(如果字符串化($func_name)=索引{
|^^^^^^^^^^^不是函数
...
31 |/comp{
32 | |结构S{
33 | |字段:字符串,
34 | |         }
...  |
42 | |         }
43 | |     }
|在这个宏调用中
|
=注意:此错误源于宏(在夜间构建中,使用-Z宏反向跟踪运行以获取更多信息)
帮助:使用“!”调用宏
|
19 |$(如果字符串化!($func_name)=索引{
|                               ^
错误[E0425]:在此作用域中找不到值'method1'
-->src/main.rs:36:20
|
36 |发布fn方法1(){
|^^^^^^^^在此范围内找不到
错误[E0425]:在此作用域中找不到值'method2'
-->src/main.rs:39:20
|
39 |发布fn方法2(){
|^^^^^^^^在此范围内找不到
错误[E0308]:类型不匹配
-->src/main.rs:19:19
|
19 |$(如果字符串化($func_name)=索引{
|  ___________________^
20 | |返回$func_name;/(***)
21 | |                 })*
||uuuuuuuuuuuuuuuuuuuuuu^预期引用,找到`()`
...
31 |/comp{
32 | |结构S{
33 | |字段:字符串,
34 | |         }
...  |
42 | |         }
43 | |     }
|在这个宏调用中
|
=注意:预期引用`&'static(dyn std::ops::Fn()+'static)`
找到的单位类型为“”()`
=注意:此错误源于宏(在夜间构建中,使用-Z宏反向跟踪运行以获取更多信息)

如何完成它?

首先,我要感谢@Shepmaster,如果您的问题不复杂,您的建议适用于大多数情况。但是需要解决一个
结构,一个由用户提供的代码块,在这种情况下,我唯一能想到的方法就是使用宏规则来实现它

过了一段时间,我终于完成了。 简言之,就我们而言,我们可以做到

fn get_method(ind: &str) -> Option<&dyn Fn()> {
    // the default type of $name::$func is fn(), function pointer
    // it is recommended to convert into &dyn Fn() if you impl many methods
    let methods = vec![ $(&$name::$func as &dyn Fn()),* ];
    let inds = vec![$(stringify!($func)),*];
    let mut i = 0;
    for item in inds.iter() {
        if item == &ind {
            break;
        } else {
            i +=1;
        }
     }
     if i <= inds.len() - 1 {
         Some(methods[i])
     } else {
         None
     }
     
}
fn获取方法(ind:&str)->选项{
//$name::$func的默认类型是fn(),函数指针
//如果使用了许多方法,建议将其转换为&dyn Fn()
let methods=vec![$(&$name::$func as&dyn Fn()),*];
设inds=vec![$(stringify!($func)),*];
设muti=0;
对于inds.iter()中的项目{
如果项==&ind{
打破
}否则{
i+=1;
}
}

如果我认为您的问题可能由的答案回答。如果不是,请您的问题解释差异。否则,我们可以将此问题标记为已回答。虽然重复返回字段,但返回函数指针应该是等效的。一如既往,在尝试创建宏之前,请先手工编写代码。