But
struct S<T> {
s: T
}
needs to own a value, and a reference wouldn't allow it to own that value.
The problem would then occur later when you want to use the value. A function might require that T: Deref<Target = U>, U: Tr
. Then, if T
is an Rc<i32>
, it works. But if T
is an i32
, it won't work. And if we make T
to be a &'a i32
, we introduce another lifetime (and need to store the integer somewhere else).
Yes, that's what I meant with "unwieldy". It's not very nice. I do see Deref
as an alternative, but then you need something like deref_owned::Owned
if you want to store an owned value directly (or resort to Box
or Cow::Owned
as workaround).
Example:
use std::borrow::Borrow;
use std::marker::PhantomData;
use std::ops::Deref;
trait Tr {
fn use_tr(&self);
}
impl Tr for i32 {
fn use_tr(&self) {
println!("I'm integer {}.", self);
}
}
struct S<T, U> {
s: T,
phantom: PhantomData<fn(&T) -> &U>,
}
impl<T, U> S<T, U> {
fn new(s: T) -> Self {
Self {
s,
phantom: PhantomData,
}
}
}
impl<T, U> S<T, U>
where
T: Borrow<U>,
U: Tr,
{
fn foo(&self) {
self.s.borrow().use_tr();
}
}
struct SWithDeref<T> {
s: T,
}
impl<T> SWithDeref<T> {
fn new(s: T) -> Self {
Self {
s,
}
}
}
impl<T, U> SWithDeref<T>
where
T: Deref<Target = U>,
U: Tr,
{
fn foo(&self) {
self.s.use_tr();
}
}
fn main() {
let a = S::new(45i32);
a.foo();
let b = S::<_, i32>::new(std::rc::Rc::new(49i32));
b.foo();
//let c = SWithDeref::new(45i32); // fails
let c = SWithDeref::new(std::borrow::Cow::Owned::<i32>(99i32));
c.foo();
let d = SWithDeref::new(std::rc::Rc::new(101i32));
d.foo();
}
Agreed, and I did it in the above Playground.
Alternatively you could use:
- let c = SWithDeref::new(std::borrow::Cow::Owned::<i32>(99i32));
+ let c = SWithDeref::new(Box::new(99i32));
But that's an extra heap allocation.
Or you use another more simple "deref owned" wrapper, which has no type parameter.