import std.stdio;
import std.typecons;
import std.string;
// This type's opDispatch removes the need for string in the flag name.
struct FlagFromBool {
auto opDispatch(string flagName)(bool value) {
mixin (format!q{
return value ? Yes.%s : No.%s;
}(flagName, flagName));
}
}
// A convenience function to remove the need for empty struct construction parenthesis.
auto flagFromBool() {
return FlagFromBool();
}
// Unfortunately, the type name still requires string flag names:
void bar(Flag!"foo" flag) {
writeln("called with ", flag);
}
void main() {
// However, the expressions don't need a string:
bar(flagFromBool.foo(false));
bar(flagFromBool.foo(true));
}struct FlagImpl(string name) { bool value; alias value this; }
struct Flag { alias opDispatch(string name) = FlagImpl!name; }
struct Yes { static auto opDispatch(string name)() { return FlagImpl!name(true); } }
struct No { static auto opDispatch(string name)() { return FlagImpl!name(false); } }
void fun(Flag.foo a) {} // Look ma, no quotes!
unittest { fun(Yes.foo); fun(Flag.foo(true)); }
But if you use D as a BetterC compiler, then the D compiler can check the O/B rules in the code.
Functions that are O/B checked are marked with the `@live` attribute, meaning that you'll be able to incrementally use O/B in the code. This is much like how you can use the `pure` attribute to incrementally write functionally pure code.
Google took me right back to your comment.
For whatever reason I found all this rather cute (and apologies to any actual D programmers if I've misread this whole situation).