我正在开发一个我有结构和特征的应用程序:Foo
和Bar
。
Foo
拥有一堆Bar
个,不同的Foo
拥有不同的Bar
s。我需要根据Foo
的{{1}}来过滤Bar
。我尝试做的是给每个Bar
一个标志的实现,然后使用所有标志来识别Bar
个Foo
拥有的。{/ p>
虽然我不确定这是进行此类过滤的最佳方法,但它确实有效。问题是我必须为每种类型管理每个标志,我不能重复标记或跳过它们所以我想在编译时(或运行时自动执行此操作,只要它遵循相同的约束) )。
这是我最近解决这个问题的尝试:
#[macro_use]
extern crate lazy_static;
static mut V : u32 = 0u32;
trait Mask<T> {
fn mask() -> u32 {
unsafe {
V = V + 1;
println!("v {}", V);
lazy_static!(static ref VALUE : u32 = unsafe{V};);
*VALUE
}
}
}
#[derive(Default)]
struct A;
#[derive(Default)]
struct B;
impl Mask<A> for A {}
impl Mask<B> for B {}
fn main() {
println!("{}", A::mask());
println!("{}", B::mask());
println!("{}", A::mask());
println!("{}", A::mask());
println!("{}", B::mask());
}
结果:
v 1
1
v 2
1
v 3
1
v 4
1
v 5
1
这是我从C ++模板中获得的一个想法,如果我没记错的话,会为每个Mask<T>
实现生成不同的类型,mask()
调用对于同一类型将是唯一的,但是不同其他类型之间。它在Rust中不起作用,但我不太了解Rust的泛型类型来猜测原因。我也尝试过使用宏,但我不知道是否有办法在宏调用之间保存状态。
有没有办法实现这个目标?还有什么我可以尝试进行这种过滤吗?
这不是Generating unique ID's for types at compile time的重复。除非有办法使用17767285367811814831
这样的数字为每种类型创建位标志,这是TypeId
给我的。
我最终想要的是每种类型都是这样的:
struct A;
struct B;
//[...]
struct N;
impl Mask for A {
fn mask() -> u32 {
1 << 0
}
}
impl Mask for B {
fn mask() -> u32 {
1 << 1
}
}
//[...]
impl Mask for N {
fn mask() -> u32 {
1 << ?N?
}
}
答案 0 :(得分:2)
如果您可以将所有类型列在一起,则可以使用宏并使用增加的枚举判别符序列来完成此操作:
trait Mask {
fn mask() -> u32;
}
macro_rules! make_masks {
($($t:ident),+) => {
enum Masks {
$($t),+
}
$(
impl Mask for $t {
fn mask() -> u32 {
1 << (Masks::$t as u32)
}
}
)+
};
}
struct A;
struct B;
struct C;
make_masks!(A, B, C);
fn main() {
// Output is: 1, 2, 4
println!("{:x}, {:x}, {:x}", A::mask(), B::mask(), C::mask());
}