Inside static if condition, the logical operators || and && will be evaluated lazily.
static if (true || error) { pragma(msg, "OK"); }
else { pragma(msg, "NG"); }
// --> prints "OK"
This is useful feature, but it doesn't work on static assert condition.
static assert(true || error);
// --> Error: undefined identifier error
This is inconsistent. I think static assert should also evaluate the condition lazily.
----
There's one associated bug.
static if (is(typeof(true || error))) { pragma(msg, "OK"); }
else { pragma(msg, "NG"); }
// --> prints "OK"
The expression "true || error" should not have valid type, but inside static if condition, the lazy evaluation is incorrectly invoked. It's definitely a bug.
----
Template constraint is the one another place for "static condition".
Currently it behaves like "static if" condition. Its behavior should also be fixed.
Comment #2 by andrej.mitrovich — 2013-09-15T04:45:33Z
I would find it even more useful if we extended this to templates, for example here's the workaround code I have to use in one of my libraries:
alias storages = ParameterStorageClassTuple; // from Phobos
/**
Check whether $(D T) is a handler function which
can be called with the $(D Types).
*/
template isEventHandler(T, Types...)
if (isSomeFunction!T)
{
alias stores = storages!T;
// eager evaluation workaround
static if (!stores.length)
enum bool isEventHandler = false;
else
enum bool isEventHandler = is(typeof(T.init(Types.init))) &&
stores[0] == stcType.scope_ &&
is(ReturnType!T == void);
}
If I'm not using this "static if", the "stores[0]" code will issue a compiler error (out of bounds) if there are no parameters. But, "is(typeof(T.init(Types.init)))" would already fail before it, however it's not lazy so "stores[0]" is evaluated eagerly and the compiler emits an error.
Can we do anything about this? Perhaps enabling lazy evaluation for manifest constants in an eponymous template would work.. I'm not sure.
Comment #3 by andrej.mitrovich — 2013-09-15T04:46:13Z