Reputation:
I am trying to find a way to group different traits so that the generic variable can hold these traits.
For example, I am trying to have T such it's with the traits io::Read + io::Write + io::Seek . Now, that can be easily done in rust using the following code:
pub trait RWS: io::Read + io::Write + io::Seek{}
impl<T> RWS for T where T: io::Read + io::Write + io::Seek{}
However, the problem comes when trying to have a function that takes in BufReader, because BufReader doesn't implement io::Write.
Therefore, is there a possibility to implement something that looks like the following for a general type that can be either one?
pub trait RWS: io::Read || io::Write || io::Seek{}
impl<T> RWS for T where T: io::Read || io::Write || io::Seek{}
Upvotes: 0
Views: 400
Reputation: 3386
If you just need a field that can store anything implementing one of these three traits at a time, I would suggest using a simple enum:
enum RWS<'a> { // The lifetime parameter can be omitted if you will only be storing fields of `'static` type.
Read(Box<dyn Read + 'a>),
Write(Box<dyn Write + 'a>),
Seek(Box<dyn Seek + 'a>),
}
You could add from_read
, from_write
, from_seek
constructors to this enum for convenience, and match on it in your struct's methods.
However, there are some limitations to this approach. Since it takes ownership of the value and erases its concrete type, you cannot do something like the following:
let bufreader: std::io::BufReader = /* ... */;
self.rws = RWS::Read(Box::new(bufreader));
// later...
if let self.rws = RWS::Read(val) {
self.rws = RWS::Seek(val); // compile error, even though `BufReader` impls `Seek`
}
Upvotes: 0