如何实现 TraitId?
How to implement a TraitId?
std::any
模块包含一个 TypeId
。我想实现一个等效的 TraitId
,这是唯一标识特征的某种方式。
此实现不必是 "entirely automated",但如果我可以依靠一些自动化并避免自己分配 ID,它会更容易一些。
到目前为止,我的 "best" 想法是为自己创建一个标记类型,然后在其上实现所有特征(健康地滥用 panic!()
),然后使用 std::raw::TraitObject
来从特征表示中获取 v-ptr 并使用 that 作为我的唯一标识符。
struct Marker;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
struct TraitId { id: *mut () }
fn trait_id<T: ?Sized>() -> TraitId
where Marker: T
{
let m = Marker { a: 1 };
let t: &T = &m;
let id: u64 = unsafe {
let r: raw::TraitObject = mem::transmute(t);
mem::transmute(r.vtable)
};
TraitId { id: id }
}
这似乎是个好主意,直到 (link):
<anon>:14:19: 14:20 error: `T` is not a trait
<anon>:14 where Marker: T
^
有谁知道如何约束 T
所以它是一个特征或制造一个(每个特征唯一)TraitId
?
滥用 TypeId
获得 TraitId
有效。
#![feature(core)]
fn main() {
println!("{:?}", trait_id::<Clone>());
println!("{:?}", trait_id::<Sync>());
}
use std::marker::{Reflect};
use std::any::TypeId;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
struct TraitId(TypeId);
fn trait_id<T: ?Sized + Reflect + 'static>() -> TraitId
{
TraitId(TypeId::of::<T>())
}
std::any
模块包含一个 TypeId
。我想实现一个等效的 TraitId
,这是唯一标识特征的某种方式。
此实现不必是 "entirely automated",但如果我可以依靠一些自动化并避免自己分配 ID,它会更容易一些。
到目前为止,我的 "best" 想法是为自己创建一个标记类型,然后在其上实现所有特征(健康地滥用 panic!()
),然后使用 std::raw::TraitObject
来从特征表示中获取 v-ptr 并使用 that 作为我的唯一标识符。
struct Marker;
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
struct TraitId { id: *mut () }
fn trait_id<T: ?Sized>() -> TraitId
where Marker: T
{
let m = Marker { a: 1 };
let t: &T = &m;
let id: u64 = unsafe {
let r: raw::TraitObject = mem::transmute(t);
mem::transmute(r.vtable)
};
TraitId { id: id }
}
这似乎是个好主意,直到 (link):
<anon>:14:19: 14:20 error: `T` is not a trait
<anon>:14 where Marker: T
^
有谁知道如何约束 T
所以它是一个特征或制造一个(每个特征唯一)TraitId
?
滥用 TypeId
获得 TraitId
有效。
#![feature(core)]
fn main() {
println!("{:?}", trait_id::<Clone>());
println!("{:?}", trait_id::<Sync>());
}
use std::marker::{Reflect};
use std::any::TypeId;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
struct TraitId(TypeId);
fn trait_id<T: ?Sized + Reflect + 'static>() -> TraitId
{
TraitId(TypeId::of::<T>())
}