2016-11-10 70 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

感謝來自@futile & @oli_obk_的IRC幫助,下面是該問題代碼的一個工作示例。

  • PtrAnyPtrAnyFuncs需要採取一種類型。
  • PtrAnyFuncs需要使用assosiated類型,所以new的參數可以在*mut*const之間變爲通用。
  • Deref宣佈它去引用Deref<Target=T>

工作代碼的類型需要:

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 
    } 
} 
相關問題