2016-11-10 10 views
0

私は、(const/mut)のメンバで主に異なるタイプを取り、それ自体がジェネリック型をとる関数を記述しようとしています。それ自体が汎用的な型を取るジェネリック関数を書くには?

質問を簡略化するために、定数または変更可能な構造体のいずれかをとる関数を記述したいと考えています。例えば:

pub struct PtrConst<T> { 
    ptr: *const T, 
} 
pub struct PtrMut<T> { 
    ptr: *mut T, 
} 

どのように私はPtrConst<SomeType>またはPtrMut<SomeType>のいずれかを取る関数を書くことができますか?


このスニペットはかなり長いですが、私はそれを単純化しようとしました。

Playbook link.

// --------------------------------------------------------------------------- 
// Test Case: This isn't working! 

// How to make a generic function? 
// See below for 'PtrConst' & 'PtrMut'. 

pub trait PtrAnyFuncs { 
    fn new() -> Self; 
    fn is_null(&self) -> bool; 
} 

pub trait PtrAny: 
    Deref + 
    Copy + 
    Clone + 
    PartialEq + 
    PtrAnyFuncs + 
    {} 

impl<TPtr> PtrAny for TPtr where 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 to 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 a as *mut MyStruct); 
    let b_ptr = PtrConst::new(&a as *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 for PtrMut<T> { 
    #[inline(always)] 
    fn new(ptr: *mut T) -> PtrMut<T> { 
     PtrMut { ptr: ptr as *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 
    } 

    // only for 'PtrMut' 
    #[inline(always)] 
    pub fn as_const(&self) -> PtrConst<T> { 
     PtrConst::new(self.ptr as *const T) 
    } 
} 

impl<T> Copy for PtrMut<T> { } 
impl<T> Clone for PtrMut<T> { 
    #[inline(always)] 
    fn clone(&self) -> PtrMut<T> { *self } 
} 

impl<T> Deref for PtrMut<T> { 
    type Target = T; 

    #[inline(always)] 
    fn deref(&self) -> &T { 
     unsafe { &*self.ptr } 
    } 
} 

impl<T> DerefMut for PtrMut<T> { 
    #[inline(always)] 
    fn deref_mut(&mut self) -> &mut T { 
     unsafe { &mut *self.ptr } 
    } 
} 

impl<T> PartialEq for 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 for PtrConst<T> { 
    #[inline(always)] 
    fn new(ptr: *const T) -> PtrConst<T> { 
     PtrConst { ptr: ptr as *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 for PtrConst<T> { } 
impl<T> Clone for PtrConst<T> { 
    #[inline(always)] 
    fn clone(&self) -> PtrConst<T> { *self } 
} 

impl<T> Deref for PtrConst<T> { 
    type Target = T; 

    #[inline(always)] 
    fn deref(&self) -> &T { 
     unsafe { &*self.ptr } 
    } 
} 

// no DerefMut for PtrConst, only PtrMut 
impl<T> PartialEq for PtrConst<T> { 
    fn eq(&self, other: &PtrConst<T>) -> bool { 
     self.ptr == other.ptr 
    } 
} 

答えて

2

ソリューションは、指示先のタイプの上に形質は、一般的なようにすることです:錆が抽象的なことができないので、これは、あなたのリンクされたコードの例を修正していないこと

pub trait PtrAny<T>: ... 

impl<T, TPtr> PtrAny<T> for TPtr where TPtr: ... 

は注意オーバー(非)変異性。

0

IRCの@futile & @oli_obk_のおかげで、ここに質問のコードの実例があります。

  • PtrAnyおよびPtrAnyFuncsが必要です。
  • PtrAnyFuncsを指定する必要があります。したがって、newへの引数は、*mut*constの間で汎用にすることができます。

    pub trait PtrAnyFuncs<T> { 
        type InnerPtr; 
    
        fn new(ptr: Self::InnerPtr) -> Self; 
        fn is_null(&self) -> bool; 
    } 
    
    pub trait PtrAny<T>: 
        Deref<Target=T> + 
        Copy + 
        Clone + 
        PartialEq + 
        PtrAnyFuncs<T> + 
        {} 
    
    impl<TPtr, T> PtrAny<T> for TPtr where TPtr: 
        Deref<Target=T> + 
        Copy + 
        Clone + 
        PartialEq + 
        PtrAnyFuncs<T> + 
        {} 
    
    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 to 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 a as *mut MyStruct); 
        let b_ptr = PtrConst::new(&b as *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<T> for PtrMut<T> { 
        type InnerPtr = *const T; 
    
        #[inline(always)] 
        fn new(ptr: Self::InnerPtr) -> PtrMut<T> { 
         PtrMut { ptr: ptr as *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 
        } 
    
        // only for 'PtrMut' 
        #[inline(always)] 
        pub fn as_const(&self) -> PtrConst<T> { 
         PtrConst::new(self.ptr as *const T) 
        } 
    } 
    
    impl<T> Copy for PtrMut<T> { } 
    impl<T> Clone for PtrMut<T> { 
        #[inline(always)] 
        fn clone(&self) -> PtrMut<T> { *self } 
    } 
    
    impl<T> Deref for PtrMut<T> { 
        type Target = T; 
    
        #[inline(always)] 
        fn deref(&self) -> &T { 
         unsafe { &*self.ptr } 
        } 
    } 
    
    impl<T> DerefMut for PtrMut<T> { 
        #[inline(always)] 
        fn deref_mut(&mut self) -> &mut T { 
         unsafe { &mut *self.ptr } 
        } 
    } 
    
    impl<T> PartialEq for 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<T> for PtrConst<T> { 
        type InnerPtr = *const T; 
    
        #[inline(always)] 
        fn new(ptr: Self::InnerPtr) -> PtrConst<T> { 
         PtrConst { ptr: ptr as *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 for PtrConst<T> { } 
    impl<T> Clone for PtrConst<T> { 
        #[inline(always)] 
        fn clone(&self) -> PtrConst<T> { *self } 
    } 
    
    impl<T> Deref for PtrConst<T> { 
        type Target = T; 
    
        #[inline(always)] 
        fn deref(&self) -> &T { 
         unsafe { &*self.ptr } 
        } 
    } 
    
    // no DerefMut for PtrConst, only PtrMut 
    impl<T> PartialEq for PtrConst<T> { 
        fn eq(&self, other: &PtrConst<T>) -> bool { 
         self.ptr == other.ptr 
        } 
    } 
    
    Deref<Target=T>

の作業コードにデリファレンスという型を宣言するために必要な

  • Deref
  • 関連する問題