能否访问结构体成员的'TypeId'?

4

有没有一种方法可以通过名称访问结构体成员的TypeId (std::any::TypeId::of::<T>)?

如果我有一个基本的结构体:

MyStruct {
    value: i64,
}

我只知道MyStructvalue,有没有一种方法可以访问TypeId::of::<i64> - 其中i64取决于value的类型?

main () {
    assert_eq!(
        TypeId::of::<i64>,
        // ^^^ this works
        type_id_of!(MyStruct, value),
        // ^^^ this is what I'm looking for
    );
}

请参考相关问题:是否可以访问结构体成员的类型以用于函数签名或声明?


这个问题是关于如何在C语言中获取结构体成员的类型以用于函数签名或声明。

1
也许加入一个工作示例会有所帮助。它会像 TypeId::of::<MyStruct::value> 这样吗?请注意,这种语法并不存在,但我认为它可以作为您尝试实现的示例。 - aochagavia
1
在问题中添加了示例。 - ideasman42
1个回答

7

只要字段是'static(其他TypeId::of不起作用),您可以使用类型检测来推断出您拥有的任何值的TypeId

fn type_id<T: 'static + ?Sized>(_: &T) -> TypeId {
    TypeId::of::<T>()
}

fn main() {
    let m = MyStruct { value: 4 };
    println!("{:?} {:?}", TypeId::of::<i64>(), type_id(&m.value));
}

接下来,利用你提出的offsetof问题中的策略,您可以创建一个宏来获取类型中的偏移量,而无需实例:

macro_rules! type_id_of {
    ($t:ty, $f:ident) => {
        {
            fn type_of<T: 'static + ?Sized>(_: &T) -> TypeId {
                TypeId::of::<T>()
            }
            let base: $t = unsafe { ::std::mem::uninitialized() };
            let result = type_of(&base.$f);
            ::std::mem::forget(base);
            result
        }
    }
}

fn main() {
    println!("{:?} {:?}", TypeId::of::<i64>(), type_id_of!(MyStruct, value));
}

这太棒了!我没想到这是可能的。 - aochagavia
1
@aochagavia:一旦你知道如何编写offset_of,其余部分就很容易了。但它并不是通用的,因为TypeId::of有这个令人讨厌的限制,即T必须是'static,但我想这方面没有什么可以做的。 - Matthieu M.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接