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.

playbook link.

// --------------------------------------------------------------------------- // 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

Popular posts from this blog

asynchronous - C# WinSCP .NET assembly: How to upload multiple files asynchronously -

aws api gateway - SerializationException in posting new Records via Dynamodb Proxy Service in API -

asp.net - Problems sending emails from forum -