I'm developing an application where I have a struct and a trait: Foo
and Bar
.
Foo
owns a bunch of Bar
s and different Foo
s have different Bar
s. I need to filter Foo
s based on which Bar
they have. What I'm trying to do is give each implementation of Bar
a bit flag and then use all the flags to identify which Bar
s a Foo
owns.
While I'm not sure this is the best approach to do this kind filtering, it works. The problem is I have to manage every single flag for every type, I can't repeat the flags or skip them so I wanted a way to do this automatically at compile time (or runtime, as long as it follows the same constraints).
This is my latest attempt at solving this:
#[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());
}
Result:
v 1
1
v 2
1
v 3
1
v 4
1
v 5
1
This is an idea I got from C++ templates which, if I recall correctly, would generate a different type for each Mask<T>
implementation and the mask()
call would be unique for the same type, but different between other types. It doesn't work in Rust but I don't understand enough about Rust's generic types to guess why. I also tried using macros, but I don't know if there's a way to save state between macro calls.
Is there a way to achieve this? Is there something else I can try for this kind of filtering?
This is not a duplicate of Generating unique ID's for types at compile time. Unless there is a way to create bit flags for each type using numbers like 17767285367811814831
, which is what TypeId
gives me.
What I want in the end is for each type to be something like this:
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?
}
}