Thread overview
reflection over templates
Mar 19, 2014
Adam D. Ruppe
Mar 19, 2014
Dicebot
Mar 19, 2014
Dicebot
Mar 19, 2014
Adam D. Ruppe
Mar 19, 2014
simendsjo
Mar 19, 2014
Andrej Mitrovic
Mar 19, 2014
Dicebot
March 19, 2014
Given:

template Foo(string T) { enum Foo = to!int(T); }

(or anything else, really)

Is there anything we can do with static if to identify it as a template?

I tried:

static if(is(Foo == template)) {} // nope, basic type expected, not template

Note that is(typeof(Foo) == function) {} is how we check for regular functions.


static if(is(typeof(Foo) == template)) {} // nope


In fact, typeof(Foo) == void... is that something we can use?


I know we can break down a template instantiation with one of the arcane is expressions, but I don't have that here, I just want to identify the template Foo as a template.

This is in the context of doing __traits(allMembers) over a module and trying to categorize every member.


Checking for a void type seems to be the closest I've gotten, but that seems awfully strange. I guess other variables can't be declared with type void, so maybe that is a unique differentiator, but still, idk about it.


And after we determine it is a template, can we extract the required arguments list like we can with a regular function at all?
March 19, 2014
Wait just a bit more https://github.com/D-Programming-Language/dmd/pull/3380 :)
March 19, 2014
As a workaround one can use set of relevant trait checks:
1) type is void
2) is not a variable or callable
3) .stringof fits "NAME(ARGS)" pattern
March 19, 2014
On 3/19/14, Adam D. Ruppe <destructionator@gmail.com> wrote:
> Is there anything we can do with static if to identify it as a template?

https://github.com/D-Programming-Language/dmd/pull/3380

> And after we determine it is a template, can we extract the required arguments list like we can with a regular function at all?

Well there's TemplateArgsOf for *instantiations*, but I'm not sure how one would do it with non-instantiations. In particular how would we create a tuple of template parameter types where one of the parameters was an alias?

E.g.:

template Foo(int, alias X);

alias Args = TypeTuple!(int, ???);

There is no "alias" type you could use in this case.
March 19, 2014
On Wednesday, 19 March 2014 at 16:18:17 UTC, Andrej Mitrovic wrote:
>> And after we determine it is a template, can we extract the
>> required arguments list like we can with a regular function at
>> all?
>
> Well there's TemplateArgsOf for *instantiations*, but I'm not sure how
> one would do it with non-instantiations. In particular how would we
> create a tuple of template parameter types where one of the parameters
> was an alias?
>
> E.g.:
>
> template Foo(int, alias X);
>
> alias Args = TypeTuple!(int, ???);
>
> There is no "alias" type you could use in this case.

One can use value instead of a type, like "alias".
March 19, 2014
On Wednesday, 19 March 2014 at 16:10:52 UTC, Dicebot wrote:
> Wait just a bit more https://github.com/D-Programming-Language/dmd/pull/3380 :)

megarox. Make it so.
March 19, 2014
On 03/19/2014 05:34 PM, Adam D. Ruppe wrote:
> On Wednesday, 19 March 2014 at 16:10:52 UTC, Dicebot wrote:
>> Wait just a bit more
>> https://github.com/D-Programming-Language/dmd/pull/3380 :)
>
> megarox. Make it so.

Nice. I have some ugly hacks that's probably full of bugs for this (look at the bottom):

template isLValue(T)
{
    enum isLValue = false;
}
/// ditto
template isLValue(alias T)
{
    enum isLValue = !isType!T && isAddressable!T && __traits(compiles, { Unqual!(TypeOf!T) t = TypeOf!(T).init; });
}
/// ditto
template isRValue(T)
{
    enum isRValue = false;
}
/// ditto
template isRValue(alias T)
{
    static if(isType!T)
        enum isRValue = false;
    else
        enum isRValue = __traits(compiles, { typeof(T) t = T; }) && !isAddressable!T;
}

template isValue(T)
{
    enum isValue = false;
}
/// ditto
template isValue(alias T)
{
    enum isValue = isLValue!T || isRValue!T;
}
/// ditto
template isType(T)
{
    enum isType = is(T);
}
/// ditto
template isType(alias T)
{
    enum isType = is(T) || isCallable!T;
}
template isTemplate(T)
{
    enum isTemplate = !(isValue!T || isType!T);
}
template isTemplate(alias T)
{
    enum isTemplate = !(isValue!T || isType!T);
}