【问题标题】:How can I define a generic struct in Rust without one of the fields being of the generic type? [duplicate]我如何在 Rust 中定义一个泛型结构,而其中一个字段不是泛型类型? [复制]
【发布时间】:2018-12-30 12:06:40
【问题描述】:

我有以下问题(简化了一点)。

有一个 trait 提供了一组不使用 self 的函数:

pub trait ImageFormat {
    fn write(data: Vec<[u8; 3]>, path: &str, ...) -> io::Result<()>;
    ...
}

有几个实现。

还有一个使用该特征的函数的结构:

pub struct Images<T: ImageFormat> {
    path: String,
    ...
}

impl<T> Images<T> where T: ImageFormat {
    pub fn setup(path: &str, ...) -> Images<T> {
        Images {
            path: String::from(path),
            ...
        }
    }

    fn write(&mut self, data: Vec<[u8; 3]>, ...) -> io::Result<()> {
        T::write(data, &self.path[..], ...)
    }
    ...
}

这不会编译,因为该结构没有 T 类型的字段。 如果我这样做,它会起作用,但感觉就像一个黑客:

pub struct Images<T: ImageFormat> {
    _image_format: Option<T>,
    path: String,
    ...
}

impl<T> Images<T> where T: ImageFormat {
    pub fn setup(path: &str, ...) -> Images<T> {
        Images {
            _image_format: None,
            path: String::from(path),
            ...
        }
    }
...
}

有什么惯用的方法吗?

【问题讨论】:

  • 如果结构不需要T,为什么不直接写“结构图像”?请描述更多你想要什么。如果你真的想“强制”它,你可以使用phamtom data,但我觉得你不应该在你的情况下使用它。
  • 结构体不需要T,但是像write on Images这样的方法确实需要它。在实践中我需要的只是类型,因为这些函数不使用 self.幻象数据似乎正是我想要的。
  • 这并没有添加信息,我仍然认为您使用了不好的工具来解决您的问题。

标签: rust


【解决方案1】:

PhantomData 可用于“标记‘表现得像’他们拥有 T 的事物”。

所以,你可以写:

pub struct Images<T: ImageFormat> {
    path: String,
    phantom: PhantomData<T>, // mark that Image "acts like" it owns a T
}

在初始化时,您只需为相应字段提供PhantomData

Images {
    path: ...
    phantom: PhantomData,
}

正如其他人所提到的,首先没有 type 参数可能会更好,但我遇到过一些情况,它们对我来说是完全合理的(例如,如果 T 提供的函数不采用 self )。

【讨论】:

  • 是的,这正是我的情况。 T 提供不带 self 的函数。
  • "如果 T 提供不带自我的功能",并且?只需将泛型添加到 impl 而不是结构,我不了解用例。相反,我认为幻像数据的典型不良用例。
  • 实际用例 (github.com/myszon/raytracer/tree/master/src/format) 有点复杂。 Images 的实例不直接使用,而是作为特征对象在运行时选择行为。因此,如果只是将泛型添加到 impl,那么当从 trait 对象调用时,编译器将无法选择正确的 write 变体。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-08
  • 1970-01-01
  • 1970-01-01
  • 2021-09-07
  • 2021-09-08
  • 2021-10-31
相关资源
最近更新 更多