Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I define a generic struct in Rust without one of the fields being of the generic type? [duplicate]

Tags:

rust

I have the following problem (it is simplified a bit).

There is a trait which supplies a set of functions which do not use self:

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

with several implementations.

There also is a struct which uses functions from that trait:

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[..], ...)
    }
    ...
}

This does not compile, because the struct does not have a field of type T. It works if I do this, but it feels like a hack:

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),
            ...
        }
    }
...
}

Is there any idiomatic way of doing this?

like image 521
myszon Avatar asked Oct 26 '25 08:10

myszon


1 Answers

PhantomData can be used "to mark things that "act like" they own a T".

So, you could write:

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

In initialization, you simply provide a PhantomData for the respective field:

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

As mentioned by others, you may be better off without the type parameter in the first place, but I have had cases where they seem perfectly reasonable to me (e.g. if T provides functions that do not take a self).

like image 71
phimuemue Avatar answered Oct 28 '25 03:10

phimuemue