2016-11-10 40 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 
    } 
} 
相关问题