我希望编写一个函数,该函数采用不同类型的函数,这些函数主要在成员的(const
/ mut
)中有所不同,它们本身采用泛型类型。
为了简化问题,我正在寻找一个带有常量或可变结构的函数。例如:
pub struct PtrConst<T> {
ptr: *const T,
}
pub struct PtrMut<T> {
ptr: *mut T,
}
我怎样才能编写一个带PtrConst<SomeType>
或PtrMut<SomeType>
?
这个片段相当长,但我试图简化它。
// ---------------------------------------------------------------------------
// 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
}
}
答案 0 :(得分:2)
解决方案是使你的特质在指针类型上具有通用性:
pub trait PtrAny<T>: ...
impl<T, TPtr> PtrAny<T> for TPtr where TPtr: ...
请注意,这并不能解决您的链接代码示例,因为Rust无法提取(非)可变性。
答案 1 :(得分:0)
感谢@futile&amp; IRC上的@oli_obk_,这是问题中代码的一个工作示例。
PtrAny
和PtrAnyFuncs
需要提供类型。PtrAnyFuncs
需要使用相关类型,因此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
}
}