有没有一种方法可以获取trait的类型名称?

3

我试图使用std::intrinsics::type_name来获取trait的类型名称,但无法编译:

#![feature(core_intrinsics)]

use std::intrinsics::type_name;

trait TestTrait: Sized {
    fn test(&self);
}

struct MyStruct {}

struct GetType {}

impl GetType {
    fn test_type<T: ?Sized>() {
        let test = unsafe { type_name::<T>() };
        println!("{:?}", test);
    }
}

fn main() {
    GetType::test_type::<i32>();
    GetType::test_type::<MyStruct>();
    GetType::test_type::<TestTrait>();
}

这是编译器返回的错误信息:

error[E0038]: the trait `TestTrait` cannot be made into an object
  --> src/main.rs:23:30
   |
23 |         GetType::test_type::<TestTrait>();
   |                              ^^^^^^^^^ the trait `TestTrait` cannot be made into an object
   |
   = note: the trait cannot require that `Self : Sized`

当我注释掉 GetType::test_type::<TestTrait>(); 这行代码时,测试的输出结果如下:

"i32"
"MyStruct"

有没有一种方法可以解决这个问题或获取trait的类型名称?


感谢@evotopid提供的解决方案

#![feature(core_intrinsics)]

use std::intrinsics::type_name;

trait TestTrait { // <--- remove `: Sized` constraint from here 
    fn test(&self);
}

struct MyStruct {}

struct GetType {}

impl GetType {
    fn test_type<T: ?Sized>() { // <--- trick is in that bound
        let test = unsafe { type_name::<T>() };
        println!("{:?}", test);
    }
}

fn main() {
    GetType::test_type::<i32>();
    GetType::test_type::<MyStruct>();
    GetType::test_type::<TestTrait>();
}

导致以下输出
"i32"
"MyStruct"
"TestTrait"
1个回答

4
这实际上在文档中已经很好地解释了:
通常,Self:Sized被用来表示该特质不应该被用作特质对象。如果特质来自于你自己的crate,请考虑移除此限制。
如果你想使用特质对象,我猜你是想要的,否则获取特质名称就没有意义,你必须从你的特质定义中移除Sized约束。
话虽如此,你确定需要内部函数吗?最有可能有更好的方法,这也将允许你在未来使用稳定的Rust。

感谢您的回答@evotopid。如果我删除Sized约束,我仍然无法使GetType::test_type::<TestTrait>();编译通过(请参见我的更新帖子以获取编译错误消息)。唯一的解决方法是调用GetType::test_type::<Box<TestTrait>>();,这相当麻烦(我仍然可以解析字符串以获得我想要的内容,但调用有点奇怪)我想将特征名称作为字符串获取,然后在映射中使用,而不是作为特征对象。我已经阅读了有关内部函数的警告,但找不到另一种获取它的方法。 - Boris
确实,我需要在test_type()函数中添加一个<T: ?Sized>的约束条件。很好的发现,谢谢。 - Boris

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