Is it possible to have a supertrait, subject to its own specific where clause? For example, I've got a custom pointer trait, and I'd like it to implement From
. However From
requires Sized
on the inner type, and I don't want to have a blanket T: Sized
restriction, I'd rather that From::from
is only available when T: Sized
happens to be true.
Specifically, this doesn't compile
trait MyPtr: Deref + From<Self::Target> {}
and this compiles but is overly restrictive
trait MyPtr: Deref + From<Self::Target> where <Self as Deref>::Target: Sized {}
I want something like (fake syntax)
trait MyPtr: Deref + { From<Self::Target> where <Self as Deref>::Target: Sized } {}
Is this somehow possible?
Is it possible to have a supertrait, subject to its own specific where clause? For example, I've got a custom pointer trait, and I'd like it to implement From
. However From
requires Sized
on the inner type, and I don't want to have a blanket T: Sized
restriction, I'd rather that From::from
is only available when T: Sized
happens to be true.
Specifically, this doesn't compile
trait MyPtr: Deref + From<Self::Target> {}
and this compiles but is overly restrictive
trait MyPtr: Deref + From<Self::Target> where <Self as Deref>::Target: Sized {}
I want something like (fake syntax)
trait MyPtr: Deref + { From<Self::Target> where <Self as Deref>::Target: Sized } {}
Is this somehow possible?
Share Improve this question asked Feb 16 at 19:58 ajpajp 2,46318 silver badges23 bronze badges 1 |1 Answer
Reset to default -1You can use a generic param to achieve this.
make MyPtr
to MyPtr<T: Sized>
and add according trait bound.
then use a blanket implementation, if the implementation is universal.
You named the trait pointer, makes me think that you want to use it as some kind of smart pointer, you might want to consider Rc
/Arc
for this kind of application, which already implemented Deref<Target=T>
and From<T>
.
I don't know your context, you might want to also consider a wrapper struct, to achieve "super trait".
use std::{ops::Deref, rc::Rc};
trait MyPtr<T: Sized>: Deref<Target = T> + From<T> {
fn print(&self) {
println!("printing . . .")
}
}
// Example Struct
struct MyStruct(i32);
impl Deref for MyStruct {
type Target = i32;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl From<i32> for MyStruct {
fn from(value: i32) -> Self {
MyStruct(value)
}
}
// impl MyPtr<i32> for MyStruct {}
// // impl for Rc
// impl<T> MyPtr<T> for Rc<T> {}
// a blanket implementation
impl<T, P> MyPtr<T> for P where P: Deref<Target = T> + From<T> {}
// // Generic Wrapper Struct
// // this might be a good option instead of using a super trait.
// struct MyWrap<T>(T);
// impl<T> Deref for MyWrap<T> {
// type Target = T;
// fn deref(&self) -> &Self::Target {
// &self.0
// }
// }
// impl<T> From<T> for MyWrap<T> {
// fn from(value: T) -> Self {
// MyWrap(value)
// }
// }
// impl MyWrap<T> {
// // impl your super trait fn here . . .
// }
fn main() {
MyStruct(0).print();
let a = Rc::new(0);
a.print();
}
trait MyPtr {
fn print(self: Rc<Self>){
println!("printing . . .");
}
}
From
implementation. – cafce25 Commented Feb 16 at 20:06