May 21, 2012
On Mon, May 21, 2012 at 5:20 PM, Manu <turkeyman@gmail.com> wrote:
> So I keep finding myself in a situation where I need to use an alias template arg, but what I actually want to alias is a MEMBER of some symbol, or even a function local.
>
> struct MyStruct
> {
>    int x;
> }
>
> template Thing(alias t)
> {
>   ...
> }
>
> MyStruct s;
>
> Thing!(s); // this is fine
> Thing!(s.x); // this doesn't work
>
> This seems like it should work intuitively, I was very surprised when it
> didn't. 's.x' can be resolved just as easily as 's' at compile time, but
> Walter said 'alias' could only understand absolute symbols, not symbol +
> offset.
> Has anyone else run into this? What's the reason for the restriction?

This works for me (DMD 2.059, Linux)

module test;

import std.stdio;

struct MyStruct
{
   int x;
}

template Thing(alias t)
{
    alias typeof(t) Thing; // just to use Thing
}

void main()
{
    MyStruct s;

    writeln(Thing!(s).stringof);
    writeln(Thing!(s.x).stringof);
}


No error with Thing!(s.x) and the result is correct. What compiler are
you using?


> I've also found I need to do this on a number of occasions: template
> Thing(alias T...)
> Ie, receive an unknown number of aliases... But that doesn't work either.

Use 'T...'  Template Parameters Tuples accept alias and types, mixed as you wish.

If you want T... to accept only types and no aliases, you'll have to
use a template constraint, using std.traits.allSatisfy!(isType, T)
With (for example):

template isType(T)
{
    enum isType = true;
}

template isType(alias a)
{
    static if (is(a))
        enum isType = true;
    else
        enum isType = false;
}



Note 1: user-defined types are *both* a type and a symbol (thus
alias-able). Cue floor wax and dessert topping.
Note 2: built-in types are... just types (wew!)

template isBuiltinType(T)
{
    enum isBuiltinType = true;
}

template isBuiltinType(alias a)
{
    enum isBuiltinType = false;
}


Note: If you have a template that makes sense for both an alias and a type, and you don't want to repeat yourself, you can use a one-element tuple:

template Thingy(T...) if (T.length == 1)
{
 ...  Use T[0] here
}