Basically, I'd like to do:
let w = TMockWriter::new();
let w = TBufferedWriter::new(w); // <---- takes the unboxed type
let w = TMockWriter::new();
let w = TBufferedWriter::new(Box::new(w) as Box<Write + Send>); // <---- takes a trait object
Is this possible?
I can't figure out a way to not require type annotations in the Box
case, but using a couple of levels of indirection via Borrow
seem to work for storing it at least (Rust Playground)
use std::io;
use std::borrow::Borrow;
use std::marker::PhantomData;
struct Foo<T: io::Read + ?Sized = io::Read, U: Borrow<T> = Box<io::Read>> {
foo: U,
marker: PhantomData<T>,
}
impl<T: io::Read + ?Sized, U: Borrow<T>> Foo<T, U> {
fn new(foo: U) -> Foo<T, U> {
Foo {
foo: foo,
marker: PhantomData,
}
}
}
fn main() {
let a = io::Cursor::new(Vec::new());
let b = Foo::new(a.clone());
let c = Foo::<io::Read, Box<io::Read>>::new(Box::new(a) as Box<io::Read>);
}
Oh dear - that looks pretty ugly. I guess what I'm asking isn't a common use case. FWIW, I've a situation where a vast majority of the time the caller will specify the bare type to a new(...)
directly, but once in a while they'll have to use a Box
(*).
(*) You may want to take a command-line argument indicating what concrete writer (tcp, unix stream, in-memory buffer etc.) to use.
not sure that this is what you want but it compiles
use std::io::Write;
struct Foo<T: Write> {
foo: T,
}
impl<T: Write> Foo<T> {
fn new(foo: T) -> Foo<T> {
Foo {
foo: foo,
}
}
}
fn main() {
let a = Vec::new();
let b = Foo::new(a.clone());
let c = Foo::new(Box::new(a));
}