Bug 4265 – It should be possible to query template parameters with __traits
Status
RESOLVED
Resolution
WORKSFORME
Severity
enhancement
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
Other
OS
All
Creation time
2010-06-02T20:33:00Z
Last change time
2015-06-09T05:13:44Z
Assigned to
nobody
Creator
nfxjfg
Comments
Comment #0 by nfxjfg — 2010-06-02T20:33:10Z
Consider you have
struct(T1, T2) Foo {
}
alias Foo!(int, float) X;
You should be able to extract (int, float) from X.
Often it is possible to get the parameters indirectly from members, but there doesn't seem to be a way to do this in the general case.
I suggest:
__traits(getTemplateParameters, X)
which would yield a (int, float) tuple.
Comment #1 by hoganmeier — 2010-06-03T16:53:07Z
What would you use that for?
Comment #2 by nfxjfg — 2010-06-03T20:05:20Z
Trass3r: meta programming. It often happened to me that I wanted to get the template params. Sometimes I had to add alias declarations just to get access to them. I think this feature would make meta programming code simpler in some cases.
PS: the example above should start with:
struct Foo(T1, T2) {
}
Comment #3 by hoganmeier — 2010-06-03T20:40:28Z
Well of course it's for metaprogramming.
But I can't imagine a usecase at the moment so I asked for some examples ;)
Comment #4 by andrej.mitrovich — 2012-12-20T14:55:16Z
As a partial workaround if you know the original template a type was instantiated with you can use:
struct Foo(T1, T2)
{
}
alias Foo!(int, float) X;
template GetParams(R, alias X)
{
static if (is(R x == X!T, T...))
{
alias T GetParams;
}
}
void main()
{
pragma(msg, GetParams!(X, Foo));
}
There's also an 'isTemplateInstance' now in std.traits.
Comment #5 by andrej.mitrovich — 2012-12-22T15:09:13Z
I can have a pull ready soon for 2 traits:
1. Get the template out of the template instance (Foo!int => Foo)
2. Get the arguments used to instantiate the template (Foo!int => (int))
However I need some good names for these. I thought about using '__traits(getTemplateArgs, T)' and '__traits(getTemplateParent, T)', any better suggestions?
Comment #6 by andrej.mitrovich — 2012-12-22T15:24:32Z
(In reply to comment #5)
> I can have a pull ready soon for 2 traits:
>
> 1. Get the template out of the template instance (Foo!int => Foo)
> 2. Get the arguments used to instantiate the template (Foo!int => (int))
>
> However I need some good names for these. I thought about using
> '__traits(getTemplateArgs, T)' and '__traits(getTemplateParent, T)', any better
> suggestions?
nazriel suggested:
'getTemplateName'
'getTemplateArgs'
I think it's better because they line up nicely.
Comment #7 by andrei — 2013-03-24T05:30:25Z
C++ lacks this particular ability and makes up for it by requiring templates to define internal aliases for type parameters. However, this is more tenuous for value parameters and simply impossible for template template parameters (in our case alias parameters). This has led to certain contortions and limitations; based on that experience I think we should add this ability.
Comment #8 by andrej.mitrovich — 2013-04-06T06:40:55Z
(In reply to comment #5)
> I can have a pull ready soon for 2 traits:
I managed to lose the branch where I implemented this. I think I only did it partially though.
@kenji: If you have this:
template T(Args...) { }
struct S(Args...) { }
alias Tint = T!int;
alias Sint = S!int;
How do you get to the 'S' declaration from the instance? I want to implement these traits:
static assert(is(__traits(getTemplateSymbol, SInt) == S));
static assert(is(__traits(getTemplateArgs, SInt) == int));
I've tried this in traits.c:
Dsymbol *s = getDsymbol(o);
TemplateInstace *ti = s->isTemplateInstance();
However that only works for Tint, and not for Sint. 's' is actually a StructDeclaration for Sint, not a TemplateInstance.
Comment #9 by thelastmammoth — 2013-06-23T18:26:08Z
(In reply to comment #4)
> As a partial workaround if you know the original template a type was
> instantiated with you can use:
>
> struct Foo(T1, T2)
> {
> }
>
> alias Foo!(int, float) X;
>
> template GetParams(R, alias X)
> {
> static if (is(R x == X!T, T...))
> {
> alias T GetParams;
> }
> }
>
> void main()
> {
> pragma(msg, GetParams!(X, Foo));
> }
>
> There's also an 'isTemplateInstance' now in std.traits.
I don't see it ? But I added it in https://github.com/D-Programming-Language/phobos/pull/1367.
Comment #10 by thelastmammoth — 2013-06-23T18:27:31Z
(In reply to comment #8)
> (In reply to comment #5)
> > I can have a pull ready soon for 2 traits:
>
> I managed to lose the branch where I implemented this. I think I only did it
> partially though.
>
> @kenji: If you have this:
>
> template T(Args...) { }
> struct S(Args...) { }
> alias Tint = T!int;
> alias Sint = S!int;
>
> How do you get to the 'S' declaration from the instance? I want to implement
> these traits:
>
> static assert(is(__traits(getTemplateSymbol, SInt) == S));
> static assert(is(__traits(getTemplateArgs, SInt) == int));
>
> I've tried this in traits.c:
>
> Dsymbol *s = getDsymbol(o);
> TemplateInstace *ti = s->isTemplateInstance();
>
> However that only works for Tint, and not for Sint. 's' is actually a
> StructDeclaration for Sint, not a TemplateInstance.
I made a pull request for this and other traits. It's in std.traits, which IMO is better than adding it to the compiler.
https://github.com/D-Programming-Language/phobos/pull/1367
Comment #11 by andrej.mitrovich — 2013-08-25T15:57:09Z
*** Issue 10890 has been marked as a duplicate of this issue. ***
Comment #12 by andrej.mitrovich — 2014-04-28T14:05:41Z
There's now TemplateArgsOf and TemplateOf in std.traits:
-----
import std.traits;
struct Foo(T1, T2)
{
}
alias Foo!(int, float) X;
pragma(msg, TemplateArgsOf!X); // (int, float)
-----