std::any
模块包含TypeId
。我想实现一个等价的TraitId
,这是一种唯一识别特征的方法。
这种实现不需要完全自动化,但如果我可以依赖某些自动化并避免自己归因于ID,那将会更容易。
我的最好"到目前为止的想法是为自己创建一个标记类型,然后在其上实现所有特征(健康滥用panic!()
)然后使用std::raw::TraitObject
从特征表示中获取v-ptr使用 作为我的唯一标识符。
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
?
答案 0 :(得分:2)
滥用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>())
}