"temporary" templates
Steven Schveighoffer
schveiguy at gmail.com
Wed Nov 27 16:15:48 UTC 2019
On 11/27/19 3:03 AM, Paul Backus wrote:
> On Tuesday, 26 November 2019 at 19:11:14 UTC, Steven Schveighoffer wrote:
>> On 11/26/19 1:59 PM, Paul Backus wrote:
>>>
>>> This will cause compilation to become non-deterministic, since the
>>> result of template evaluation can depend on the order in which
>>> declarations are semantically analyzed:
>>>
>>> enum hasFoo(T) = __traits(hasMember, T, "foo");
>>>
>>> struct S {
>>> // hasFoo!S is instantiated before the mixin is processed
>>> static if (hasFoo!S) {}
>>> mixin("int foo;");
>>> }
>>>
>>> pragma(msg, hasFoo!S); // false
>>>
>>> If for some reason the "innards" of `hasFoo!S` are discarded due to
>>> memory pressure, reconstructing them later will give a different result.
>>
>> But that's an evaluation order issue. hasFoo should be true in both
>> cases. Otherwise, you have the paradox:
>>
>> static assert(hasFoo!S == __traits(hasMember, T, "foo"))
>
> There are situations where a particular evaluation order is forced. For
> example:
>
> enum hasFoo(T) == __traits(hasMember, T, "foo");
>
> struct S {
> static if (!hasFoo!S) {
> int foo;
> }
> }
>
> static assert(hasFoo!S == __traits(hasMember, S, "foo")); // fails
>
> The condition of the static if *must* be evaluated before the body, so
> there is no way to have hasFoo!S evaluate to the same thing in both
> places without causing a paradox. Note that this is *not* an accident of
> the current compiler implementation; it follows directly from the
> definition of `static if` in the language spec.
OK, this is more of a correct argument since obviously hasFoo must be
false to add foo, but then it should be true after that. So it's still
not ideal, and still a paradox.
What I am proposing is that you can mark items as @temporary or
something like that, and those templates will be reevaluated each time.
And in the case of something like hasFoo, I'd argue it's just a thin
wrapper over a __traits call, so it probably should be reevaluated each
time.
This does not make it non-deterministic, just determined differently. In
fact, I'd say it's *more* deterministic, as evaluating templates does
not depend on weird interactions like this. And it should be opt-in to
avoid breaking code.
But it's also possible that Stefan's solution would work as well, if we
can manipulate types like variables in CTFE mode.
-Steve
More information about the Digitalmars-d
mailing list