On 09/25/2014 04:08 PM, SlomoTheBrave wrote:

> On Thursday, 25 September 2014 at 22:11:20 UTC, Mathias LANG wrote:
>> I'm a bit puzzled with the following behavior:
>>
>> ----
>> import std.typetuple, std.traits;
>>
>> struct UDAStruct {
>>     string identifier;
>> }
>>
>> class MyClass {
>>     @(UDAStruct("p1"), UDAStruct("p2"), UDAStruct("P3")) // P3 is a typo
>>       void func(int p1, string p2, float p3) {}
>> }
>>
>> unittest {
>>     alias Func = MyClass.func;
>>     enum ParamNames = ParameterIdentifierTuple!Func;
>>     enum ParamAttr = __traits(getAttributes, Func);
>>
>>     foreach (attr; ParamAttr) {
>>         template CmpName(string PName) {
>>             pragma(msg, "Instantiated for: "~PName);
>>             enum CmpName = (PName == attr.identifier);
>>         }
>>         pragma(msg, "Current attr is: "~attr.identifier);
>>         static assert(anySatisfy!(CmpName, ParamNames));

The first invocation of that line will instantiate CmpName with ParamNames, which happens to be a TypeTuple of "p1", "p2", and "p3".

> the output lines order shows there is a problem too:
>
>> Current attr is: p1
>> Instantiated for: p1
>> Instantiated for: p2
>> Instantiated for: p3

Surprisingly, that indicates that anySatisfy did instantiate CmpName with all three string values, meaning that perhaps we don't have shortcut behavior for 'bool' eponymous templates.

Copying and instrumenting anySatisfy's implementation:

template myAnySatisfy(alias F, T...)
{
    pragma(msg, "myAnySatisfy with "~[ T ]);
    static if(T.length == 0)
    {
        enum myAnySatisfy = false;
        pragma(msg, "length == 0 "~myAnySatisfy);
    }
    else static if (T.length == 1)
    {
        enum myAnySatisfy = F!(T[0]);
        pragma(msg, "length == 1 "~myAnySatisfy);
    }
    else
    {
        enum myAnySatisfy =
            myAnySatisfy!(F, T[ 0  .. $/2]) ||
            myAnySatisfy!(F, T[$/2 ..  $ ]);
        pragma(msg, "else "~myAnySatisfy);
    }
}

When I use myAnySatisfy instead of anySatisfy, I see that I am right: The last expression above does not stop instantiating after "p1". In other words, even though myAnySatisfy!(F, T[$/2 .. $ ] is unnecessary (because the first part of || is already 'true'), it gets instantiated anyway.

Current attr is: p1
["myAnySatisfy with ", "p1", "p2", "p3"]
["myAnySatisfy with ", "p1"]
Instantiated for: p1
length == 1 
["myAnySatisfy with ", "p2", "p3"]
["myAnySatisfy with ", "p2"]
Instantiated for: p2
length == 1
["myAnySatisfy with ", "p3"]
Instantiated for: p3
length == 1
else
else 
Current attr is: p2
Current attr is: P3

This looks like an enhancement request.

Ali

Reply via email to