lazy evaluation of logical operators in enum definition
Jacob Carlborg
doob at me.com
Tue Apr 17 06:54:23 UTC 2018
On Monday, 16 April 2018 at 05:57:01 UTC, Shachar Shemesh wrote:
> Consider the following program:
>
> struct S1 {
> enum member = 3;
> }
>
> struct S2 {
> enum member = 2;
> }
>
> struct S3 {
> }
>
> enum prop(T) = __traits(hasMember, T, "member") && T.member==3;
>
> pragma(msg, prop!S1);
> pragma(msg, prop!S2);
> pragma(msg, prop!S3);
>
> When compiled, it produces:
> true
> false
> test.d(12): Error: no property member for type S3
> test.d(16): Error: template instance `test.prop!(S3)` error
> instantiating
> test.d(16): while evaluating pragma(msg, prop!(S3))
>
> If I change the definition of "prop" to:
> template prop(T) {
> static if( __traits(hasMember, T, "member") && T.member==3 )
> enum prop = true;
> else
> enum prop = false;
> }
>
> then everything compiles as expected.
>
> It seems that the && evaluation does not stop when the first
> false is found.
I think the issue is better illustrated with a function:
bool prop(T)()
{
if (__traits(hasMember, T, "member"))
{
if (T.member == 3)
return true;
}
return false;
}
In this function there's no way to tell if the function is going
to be executed at compile time or at runtime. Therefore the
semantics of the whole function need to be valid. Replacing the
`if` with a `static if` would solve the problem, as you
mentioned. This works because the semantic analysis of `static
if` and CTFE evaluation of a function occurs at different phases
in the compiler. This post explains this better and in more
detail [1]. The issue is that the compiler will do the semantic
analysis of `T.member` before it has run CTFE or constant folding
on the expression.
Although, one could argue that in your case it's clear that the
expression only will be evaluated at compile time, but that's not
how the compiler works currently.
[1]
https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time
--
/Jacob Carlborg
More information about the Digitalmars-d
mailing list