【发布时间】:2021-03-08 04:51:56
【问题描述】:
我想为实现Sized + 'static 的给定类型T 获取TypeId 的一些实例。
use std::any::TypeId;
trait Comp: Sized + 'static { }
impl<T: 'static> Comp for T { }
struct Foo;
fn main() {
println!("{}", TypeId::of::<Foo>());
println!("{}", TypeId::of::<&Foo>());
println!("{}", TypeId::of::<&mut Foo>());
}
但结果不同。是的,我知道这是完全正常的行为。为了处理这个问题,我修改了这段代码如下。
use std::ops::Deref;
// Same codes are omitted...
fn main() {
println!("{}", TypeId::of::<Foo>());
println!("{}", TypeId::of::<<&Foo as Deref>::Target>());
println!("{}", TypeId::of::<<&mut Foo as Deref>::Target>());
}
现在它打印相同的值。为了对所有Comp 实现这种行为,我在下面写了。
use std::any::TypeId;
use std::ops::Deref;
trait Comp: Sized + 'static {
type Pure: Comp;
}
impl<T: 'static> Comp for T {
type Pure = T;
}
impl<T: Deref + 'static> Comp for T {
type Pure = <T as Deref>::Target;
}
struct Foo;
fn main() {
println!("{}", TypeId::of::<<Foo as Comp>::Pure>());
println!("{}", TypeId::of::<<&Foo as Comp>::Pure>());
println!("{}", TypeId::of::<<&mut Foo as Comp>::Pure>());
}
它不会编译,因为我提供了相互冲突的实现。我该如何解决这个问题?
【问题讨论】:
-
你打算用
TypeId做什么,它可能与你手头的类型相对应或不对应? -
这需要仅对类型进行操作(即“静态”方法),还是可以对值使用方法?
-
这似乎是 specialization 的教科书用法,遗憾的是尚未稳定(或接近稳定)。
-
即使在夜间,你也不能专门“研究”一个特征。可以通过How can I write a method to wrap any value in my type that can be called multiple times without requiring type annotations? 解决(使用
P: Deref<Target = T>而不是Wrapper<T>) -
但我怀疑这是一件有用的事情;正如我之前问过的,如果您不知道
TypeId属于什么类型,您将如何处理它?你不能透明地对待&T和T,所以你不能通过Any向上/向下转换。我想你可以用它索引地图吗?但这似乎只是将问题推高了一个层次,因为您获得的任何价值都将是 eitherT或&T而不是两者。这听起来很奇怪,就像你试图想象引用并不真正存在。我鼓励你不要这样做,并寻找替代方法来做你正在做的任何事情。