如何以编程方式获取结构的字段数? [英] How to programmatically get the number of fields of a struct?

查看:43
本文介绍了如何以编程方式获取结构的字段数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个如下所示的自定义结构:

I have a custom struct like the following:

struct MyStruct {
    first_field: i32,
    second_field: String,
    third_field: u16,
}

是否可以以编程方式获取结构字段的数量(例如,通过方法调用field_count()):

Is it possible to get the number of struct fields programmatically (like, for example, via a method call field_count()):

let my_struct = MyStruct::new(10, "second_field", 4);
let field_count = my_struct.field_count(); // Expecting to get 3

对于这个结构:

struct MyStruct2 {
    first_field: i32,
}

... 以下调用应返回 1:

... the following call should return 1:

let my_struct_2 = MyStruct2::new(7);
let field_count = my_struct2.field_count(); // Expecting to get count 1

有没有像 field_count() 这样的 API 还是只能通过宏获得?

Is there any API like field_count() or is it only possible to get that via macros?

如果可以通过宏实现,应该如何实现?

If this is achievable with macros, how should it be implemented?

推荐答案

是否有任何可能的 API,例如 field_count() 还是只能通过宏获得?

Are there any possible API like field_count() or is it only possible to get that via macros?

没有这样的内置 API 可以让您在运行时获取此信息.Rust 没有运行时反射(有关更多信息,请参阅这个问题).但确实可以通过 proc-macros 实现!

There is no such built-in API that would allow you to get this information at runtime. Rust does not have runtime reflection (see this question for more information). But it is indeed possible via proc-macros!

注意:proc-macros 不同于宏示例"(通过 macro_rules! 声明).后者不如 proc-macros 强大.

Note: proc-macros are different from "macro by example" (which is declared via macro_rules!). The latter is not as powerful as proc-macros.

如果可以通过宏实现,应该如何实现?

If this is achievable with macros, how should it be implemented?

(这不是对 proc-macros 的介绍;如果该主题对您来说是全新的,请先阅读别处的介绍.)

在 proc 宏(例如自定义派生)中,您需要以某种方式获取结构定义为 TokenStream.使用带有 Rust 语法的 TokenStream 的实际解决方案是通过 解析它同步:

In the proc-macro (for example a custom derive), you would somehow need to get the struct definition as TokenStream. The de-facto solution to use a TokenStream with Rust syntax is to parse it via syn:

#[proc_macro_derive(FieldCount)]
pub fn derive_field_count(input: TokenStream) -> TokenStream {
    let input = parse_macro_input!(input as ItemStruct);

    // ...
}

input 的类型是ItemStruct.如您所见,它具有 字段.在该字段上,您可以调用 iter() 以获取结构体所有字段的迭代器,然后您可以调用 count():

The type of input is ItemStruct. As you can see, it has the field fields of the type Fields. On that field you can call iter() to get an iterator over all fields of the struct, on which in turn you could call count():

let field_count = input.fields.iter().count();

现在你有你想要的了.

也许您想将这个 field_count() 方法添加到您的类型中.您可以通过自定义派生(通过在此处使用 quote 箱)来做到这一点:

Maybe you want to add this field_count() method to your type. You can do that via the custom derive (by using the quote crate here):

let name = &input.ident;

let output = quote! {
    impl #name {
        pub fn field_count() -> usize {
            #field_count
        }
    }
};

// Return output tokenstream
TokenStream::from(output)

然后,在您的应用程序中,您可以编写:

Then, in your application, you can write:

#[derive(FieldCount)]
struct MyStruct {
    first_field: i32,
    second_field: String,
    third_field: u16,
}

MyStruct::field_count(); // returns 3

这篇关于如何以编程方式获取结构的字段数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆