如何在Rust中定义通用结构而没有其中一个字段属于通用类型?

时间:2018-12-30 12:06:41

标签: rust

我有以下问题(略有简化)。

有一个特征提供了一组不使用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),
            ...
        }
    }
...
}

有什么惯用的方法吗?

1 个答案:

答案 0 :(得分:2)

PhantomData可用于“标记“行为类似”的事物,它们拥有T”。

因此,您可以编写:

set((x,y,z)

在初始化时,您只需为相应的字段提供pub struct Images<T: ImageFormat> { path: String, phantom: PhantomData<T>, // mark that Image "acts like" it owns a T }

PhantomData

正如其他人所提到的,首先不用type参数可能会更好,但是我遇到了一些对我来说似乎完全合理的情况(例如,如果Images { path: ... phantom: PhantomData, } 提供的函数不使用{ {1}}。