bearophile wrote: > To invent a software you can first find the best syntax. This seems a nice > syntax, very similar to the enum one (that ubyte is optional): > > flags ubyte Todo { > do_nothing, > walk_dog, > cook_breakfast, > deliver_newspaper, > visit_miss_kerbopple, > wash_covers > } > > Todo todo = Todo.walk_dog | Todo.deliver_newspaper | Todo.wash_covers; > if (todo == (Todo.walk_dog | Todo.deliver_newspaper)) { ... > if ((Todo.walk_dog | Todo.deliver_newspaper) in todo) { ... > if ((Todo.walk_dog | Todo.deliver_newspaper) & todo) { ... > assert((Todo.walk_dog | Todo.walk_dog) == Todo.walk_dog); // OK > > > A way to implement it with current D2 syntax: > > > alias Flags!(ubyte, "do_nothing", > "walk_dog" > "cook_breakfast" > "deliver_newspaper" > "visit_miss_kerbopple" > "wash_covers") Todo; > > > Where Flags defines a struct, "do_nothing" are compile-time constants. It > can overload 8 operators: > = == | |= in & &= opBool > > The operator ! too can be defined, but I think it looks too much like the | > so it can be omitted (other operators like ^ and ~ are possible). >
I like this idea of implementing a flag type and tried to work something out. Instead of implementing the overloads, it is also possible to generate an enum via CTFE inside a struct and forward with alias this, what do you think? I have tried this syntax, seems to work ok: alias Flags!q{ do_nothing, walk_dog, cook_breakfast, deliver_newspaper, visit_miss_kerbopple, wash_covers } Todo; It does allow this though, but perhaps that can fixed: Todo todo = Todo.walk_dog; todo |= 4; With such a type, it is easy to add some small convenience features, such as an enumToString, define property .max and implement a range that iterates over all flags set or possible values.