rust - How to write generic functions that take types which are themselves generic? -
i'm looking write function takes different types differ in (const
/ mut
) of member, take generic type.
to simplify question, i'm looking write function takes either constant or mutable struct. eg:
pub struct ptrconst<t> { ptr: *const t, } pub struct ptrmut<t> { ptr: *mut t, }
how write function takes either ptrconst<sometype>
or ptrmut<sometype>
?
this snippet rather long, i've attempted simplify it.
// --------------------------------------------------------------------------- // test case: isn't working! // how make generic function? // see below 'ptrconst' & 'ptrmut'. pub trait ptranyfuncs { fn new() -> self; fn is_null(&self) -> bool; } pub trait ptrany: deref + copy + clone + partialeq + ptranyfuncs + {} impl<tptr> ptrany tptr tptr: deref + copy + clone + partialeq + ptranyfuncs + {} fn generic_test<t: ptrany<mystruct>>(a: t) { if a.is_null() { println!("test: null"); } else { println!("test: {} {}", a.my_val_a, a.my_val_b); } } // --------------------------------------------------------------------------- // attempt use generic function struct mystruct { pub my_val_a: usize, pub my_val_b: usize, } fn main() { let mut a: mystruct = mystruct { my_val_a: 10, my_val_b: 2, }; let b: mystruct = mystruct { my_val_a: 4, my_val_b: 4, }; let a_ptr = ptrmut::new(&mut *mut mystruct); let b_ptr = ptrconst::new(&a *const mystruct); generic_test(a_ptr); generic_test(b_ptr); } // --------------------------------------------------------------------------- // ptrmut use std::ops::{ deref, derefmut, }; #[repr(c)] #[derive(hash)] pub struct ptrmut<t> { ptr: *mut t, } impl<t> ptranyfuncs ptrmut<t> { #[inline(always)] fn new(ptr: *mut t) -> ptrmut<t> { ptrmut { ptr: ptr *mut t } } #[inline(always)] fn is_null(&self) -> bool { self.ptr == ::std::ptr::null_mut() } } impl<t> ptrmut<t> { #[inline(always)] pub fn null() -> ptrmut<t> { ptrmut { ptr: ::std::ptr::null_mut() } } #[inline(always)] pub fn as_pointer(&self) -> *mut t { self.ptr } // 'ptrmut' #[inline(always)] pub fn as_const(&self) -> ptrconst<t> { ptrconst::new(self.ptr *const t) } } impl<t> copy ptrmut<t> { } impl<t> clone ptrmut<t> { #[inline(always)] fn clone(&self) -> ptrmut<t> { *self } } impl<t> deref ptrmut<t> { type target = t; #[inline(always)] fn deref(&self) -> &t { unsafe { &*self.ptr } } } impl<t> derefmut ptrmut<t> { #[inline(always)] fn deref_mut(&mut self) -> &mut t { unsafe { &mut *self.ptr } } } impl<t> partialeq ptrmut<t> { fn eq(&self, other: &ptrmut<t>) -> bool { self.ptr == other.ptr } } // --------------------------------------------------------------------------- // ptrconst #[repr(c)] #[derive(hash)] pub struct ptrconst<t> { ptr: *const t, } impl<t> ptranyfuncs ptrconst<t> { #[inline(always)] fn new(ptr: *const t) -> ptrconst<t> { ptrconst { ptr: ptr *const t } } #[inline(always)] fn is_null(&self) -> bool { self.ptr == ::std::ptr::null_mut() } } impl<t> ptrconst<t> { #[inline(always)] pub fn null() -> ptrconst<t> { ptrconst { ptr: ::std::ptr::null_mut() } } #[inline(always)] pub fn as_pointer(&self) -> *const t { self.ptr } } impl<t> copy ptrconst<t> { } impl<t> clone ptrconst<t> { #[inline(always)] fn clone(&self) -> ptrconst<t> { *self } } impl<t> deref ptrconst<t> { type target = t; #[inline(always)] fn deref(&self) -> &t { unsafe { &*self.ptr } } } // no derefmut ptrconst, ptrmut impl<t> partialeq ptrconst<t> { fn eq(&self, other: &ptrconst<t>) -> bool { self.ptr == other.ptr } }
the solution make trait generic on pointee type:
pub trait ptrany<t>: ... impl<t, tptr> ptrany<t> tptr tptr: ...
note doesn't fix linked code example, because rust can't abstract on (non-)mutability.
Comments
Post a Comment