Comment #0 by ellery-newcomer — 2014-08-24T18:11:39Z
Passing an instantiated eponymous function template to __traits(parent,) yields a symbol that points to the function passed in. In G in the following code, I'm seeing this behavior:
f __traits(parent, f)
------ ----------------------
a tok
b!int.c __T1bTiZ
t!int t
code:
import std.typetuple;
int a(int i) {
return i;
}
template b(T) {
int c(T t) {
return 1;
}
}
int t(T)(T g) {
return 1;
}
template G(alias f) {
static assert(is(typeof(f) == function));
pragma(msg, __traits(identifier, f));
alias Parent = TypeTuple!(__traits(parent, f))[0];
pragma(msg, __traits(identifier, Parent));
static assert(!is(typeof(Parent) == typeof(f)), "I'm my own parent?");
}
void main(){
alias y = G!(a);
alias z = G!(t!int); // fails in here
}
Comment #1 by slavo5150 — 2015-01-25T05:55:55Z
Looks like this might be the same as Issue 12496
Comment #2 by b2.temp — 2016-11-05T16:16:38Z
=========
import std.meta;
template Parent(T)
{
alias Parent = AliasSeq!(__traits(parent, T))[0];
}
unittest
{
class A(T){}
static assert(A!int.stringof != Parent!(A!int).stringof);
}
=========
yields: Error: static assert ("A!int" != "A!int") is false
the longer form
=========
import std.meta;
template Parent(T)
{
alias Parent = AliasSeq!(__traits(parent, T))[0];
}
unittest
{
template B(T){class B{}}
alias T = B!int;
static assert(is(T));
static assert(T.stringof != Parent!T.stringof);
}
=========
yields: Error: static assert ("B!int" != "B!int") is false
too.
Comment #3 by b2.temp — 2016-11-05T18:06:52Z
Strangely enough this bug can lead to think that we can detect an eponymous template:
==========
template isTemplateInstance(alias T : Base!Args, alias Base, Args...)
{
enum isTemplateInstance = is(typeof(T));
}
template isTemplateInstance(T : Base!Args, alias Base, Args...)
{
enum isTemplateInstance = is(T);
}
template isTemplateInstance(T)
{
enum isTemplateInstance = false;
}
template isTemplateInstance(alias T)
{
enum isTemplateInstance = isTemplateInstance!(typeof(T));
}
template isEponymousTemplate(T)
{
static if (is(T == class) || is(T == interface) || is(T == struct) || is(T == union))
{
enum p = __traits(parent, T).stringof == T.stringof;
enum isEponymousTemplate = p && isTemplateInstance!T;
}
else
enum isEponymousTemplate = false;
}
unittest
{
class A(T){}
struct B(T){}
static assert(isEponymousTemplate!(A!int));
static assert(isEponymousTemplate!(B!int));
static assert(!isEponymousTemplate!int);
template C(T)
{
class C{}
}
static assert(isEponymousTemplate!(C!int));
}
unittest
{
template A(T)
{
class A{}
}
static assert(isEponymousTemplate!(A!int));
template B(T)
{
class A{}
}
static assert(!isEponymousTemplate!(B!int.A));
class C(T){}
static assert(!isEponymousTemplate!int);
A!int a;
static assert(isEponymousTemplate!a);
}
==========
Indeed we can detect it but we can't get the parent !
What's happen is that "isEponymousTemplate" yield true for an eponymous template because the template itself points to its argument !
Comment #4 by slavo5150 — 2018-01-29T07:51:05Z
(In reply to Basile B. from comment #2)
> =========
> import std.meta;
>
> template Parent(T)
> {
> alias Parent = AliasSeq!(__traits(parent, T))[0];
> }
>
> unittest
> {
> class A(T){}
> static assert(A!int.stringof != Parent!(A!int).stringof);
> }
> =========
>
> yields: Error: static assert ("A!int" != "A!int") is false
>
>
> the longer form
>
> =========
> import std.meta;
>
> template Parent(T)
> {
> alias Parent = AliasSeq!(__traits(parent, T))[0];
> }
>
> unittest
> {
> template B(T){class B{}}
> alias T = B!int;
> static assert(is(T));
> static assert(T.stringof != Parent!T.stringof);
> }
> =========
>
> yields: Error: static assert ("B!int" != "B!int") is false
These two tests now pass in v2.078.1
Comment #5 by destructionator — 2020-05-24T17:24:28Z
Here's something related I just came upon:
template wrap(string foo) {
enum wrap = foo;
}
pragma(msg, __traits(parent, wrap!"lol")); // says lol
pragma(msg, __traits(parent, __traits(parent, wrap!"lol"))); // says argument "lol" has no parent
So in the first one, it appears it evaluates to the outer template which is then instantly evaluated back to the enum literal. Then the second one sees the literal and says literals have no parents.
Quite bizarre indeed.
Comment #6 by robert.schadek — 2024-12-13T18:24:50Z