Thread overview
bug with is(T == TI!TP) expression: captures templated structs but not templated functions?
Jun 25, 2013
Timothee Cour
Jun 25, 2013
Timon Gehr
Jun 25, 2013
Dicebot
Jun 25, 2013
Timothee Cour
June 25, 2013
template Test(alias T){
  static if(is(T == TI!TP, alias TI, TP)){
    enum Test=true;
  }
  else{
    enum Test=false;
  }
}

struct A(T){}
void foo(T)(T a){}

void main(){
  static assert(Test!(A!double));
  static assert(!Test!(foo!double)); //why is Test false?
}

This is blocking my pull request to make fullyQualifiedName/GetTemplateParent/GetTemplateArguments work on everything: right now it fails on templated functions.


June 25, 2013
On 06/25/2013 12:32 PM, Timothee Cour wrote:

It is not a bug.

> template Test(alias T){
>    static if(is(T == TI!TP, alias TI, TP)){
>      enum Test=true;
>    }
>    else{
>      enum Test=false;
>    }
> }
>
> struct A(T){}
> void foo(T)(T a){}
>
> void main(){
>    static assert(Test!(A!double));
>    static assert(!Test!(foo!double)); //why is Test false?
> }
>

Because foo!double is not a type. All forms of the is-expression check whether the first argument is a valid type.

> This is blocking my pull request to make
> fullyQualifiedName/GetTemplateParent/GetTemplateArguments work on
> everything: right now it fails on templated functions.
>


June 25, 2013
On Tuesday, 25 June 2013 at 10:32:14 UTC, Timothee Cour wrote:
> template Test(alias T){
>   static if(is(T == TI!TP, alias TI, TP)){
>     enum Test=true;
>   }
>   else{
>     enum Test=false;
>   }
> }
>
> struct A(T){}
> void foo(T)(T a){}
>
> void main(){
>   static assert(Test!(A!double));
>   static assert(!Test!(foo!double)); //why is Test false?
> }
>
> This is blocking my pull request to make
> fullyQualifiedName/GetTemplateParent/GetTemplateArguments work on
> everything: right now it fails on templated functions.

As I have already mentiond in comments to that pull (probably was not clear enough), it is not really a bug, but one of many difficulties when working with function types in generic code.

When you pass a function there, you pass function symbol, not its type. For aggregates those are interchangeable, not so for functions. Most simple example:

    void foo(int x) {}
    pragma( msg, is(foo == function) ); // false
    pragma( msg, is(typeof(foo) == function) ); // true

So you simply can't do any type matching with T when T is function alias.

However, when you take typeof(T), all template information gets lost and you get type of specific instantiation.

Looks like not a bug, but lack of required tool.
June 25, 2013
On Tue, Jun 25, 2013 at 3:47 AM, Dicebot <public@dicebot.lv> wrote:

> On Tuesday, 25 June 2013 at 10:32:14 UTC, Timothee Cour wrote:
>
>> template Test(alias T){
>>   static if(is(T == TI!TP, alias TI, TP)){
>>     enum Test=true;
>>   }
>>   else{
>>     enum Test=false;
>>   }
>> }
>>
>> struct A(T){}
>> void foo(T)(T a){}
>>
>> void main(){
>>   static assert(Test!(A!double));
>>   static assert(!Test!(foo!double)); //why is Test false?
>> }
>>
>> This is blocking my pull request to make fullyQualifiedName/**GetTemplateParent/**GetTemplateArguments work on everything: right now it fails on templated functions.
>>
>
> As I have already mentiond in comments to that pull (probably was not clear enough), it is not really a bug, but one of many difficulties when working with function types in generic code.
>
> When you pass a function there, you pass function symbol, not its type. For aggregates those are interchangeable, not so for functions. Most simple example:
>
>     void foo(int x) {}
>     pragma( msg, is(foo == function) ); // false
>     pragma( msg, is(typeof(foo) == function) ); // true
>
> So you simply can't do any type matching with T when T is function alias.
>
> However, when you take typeof(T), all template information gets lost and you get type of specific instantiation.
>
> Looks like not a bug, but lack of required tool.
>


So how can I decompose alias fun=foo!double into template parent / template
arguments?
The compiler knows this so there has to be a way to retrieve it. If not,
then we're back in my previous proposal, adding:
__traits(templateParent, symbol)
__traits(templateArguments, symbol)