rust - 使用特征作为幻像类型

标签 rust phantom-types

在 Rust 中,我想使用幻像类型来正确键入一个简单的 id:

struct Id<T> {
    val: u32,
    _type: PhantomData<T>,
}
在初稿版本中,我使用了具体结构作为 T , 一切都好。然后在使用不同数据源的更精细的版本中,这些结构变成了特征。比方说:
trait MyArticle {
    fn get_id() -> Id<MyArticle>;
}
但是使用traits作为幻像类型会带来问题:
  • 编译器让我声明 T: ?Sized , 好像 T 的大小可能需要。我可以忍受,但作为 PhantomData<T> 的目的是告诉T不会用,不知道有没有别的办法?
  • 我收到警告:“不推荐使用没有明确 'dyn' 的特征对象”。我可以用全局 #![allow(bare_trait_objects)] 摆脱它,但是这个警告在其他方面很有用,我不想这样做。有没有办法允许bare_trait_object只有“当用作 Id<T> 的类型参数时”?

  • 我当前的解决方案是在空结构和特征之间复制名称类型:
    struct MyArticle_ {};
    
    trait MyArticle {
        fn get_id() -> Id<MyArticle_>;
    }
    
    这很尴尬,但我找不到更好的。

    最佳答案

    您的样本的问题在于了解特征是什么。实际上是不是 一个类型(这就是编译器要求 T: ?Sized 的原因),但需要一个类型。因此解决方案相当简单:想出一个“真正的”类型。你用结构声明做对了,它可以是一种选择。但通常使用关联类型更方便:

    trait MyArticle {
        type T;
    
        fn get_id() -> Id<Self::T>
        where
            Self::T: MyArticle;
    }
    
    // so given impls
    struct X;
    
    impl MyArticle for X {
        type T = u32;
        fn get_id() -> Id<u32> {
            todo!()
        }
    }
    
    impl MyArticle for u32 {
        type T = u32;
        fn get_id() -> Id<u32> {
            todo!()
        }
    }
    
    所以最后,您可以调用X::get_id() ,或完全合格的版本:<X as MyArticle>::get_id()此外,您可以阅读 there为什么fn get_id() -> Id<Box<dyn MyArticle>>不起作用。

    关于rust - 使用特征作为幻像类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67933762/

    相关文章:

    static - 为什么在同一范围内可以有多个具有静态生命周期的可变引用

    pointers - Rust - 包装 FFI 指针

    Haskell:具有幻像变量的数据的异构列表

    haskell - 为什么这个 Haskell 表达式可以编译?

    rust - 如何将附加参数传递给特征的显示或调试实现?

    rust - 添加到基于 RefCell 构建的二叉树时,借用的值不会存在足够长的时间

    rust - 如何在 Substrate FRAME 托盘内的结构中包含 <T as Trait>::Blocknumber

    scala - 如何在 Phantom 中从 SetColumn[String] 选择字段

    typescript - 如何使幻像类型与 TypeScript 中的方法一起使用?