www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Identifier hierarchy

reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
Just to check. If you have a piece of code like "foo.bar.baz", 
you can get the full hierarchy, for instance with stringof:


      static assert(foo.bar.baz.stringof == "foo.bar.bar");

But once you pass foo.bar.baz to a template, there's no way to 
recover the full path, is there? You only get baz. You can ask 
for the __traits(parent, baz), but you only get the type of bar, 
not the identifier.

Assuming you pass the foo.bar.baz normally (alias arg) to the 
template (not as a string, for instance), there's no workaround 
for this, is there?
Jun 11 2018
parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Monday, 11 June 2018 at 12:38:33 UTC, Luís Marques wrote:
 Just to check. If you have a piece of code like "foo.bar.baz", 
 you can get the full hierarchy, for instance with stringof:


      static assert(foo.bar.baz.stringof == "foo.bar.bar");
Are you looking for this: https://dlang.org/phobos/std_traits.html#fullyQualifiedName ? Mike
Jun 11 2018
parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Monday, 11 June 2018 at 12:59:01 UTC, Mike Franklin wrote:
 On Monday, 11 June 2018 at 12:38:33 UTC, Luís Marques wrote:
 Just to check. If you have a piece of code like "foo.bar.baz", 
 you can get the full hierarchy, for instance with stringof:


      static assert(foo.bar.baz.stringof == "foo.bar.bar");
Are you looking for this: https://dlang.org/phobos/std_traits.html#fullyQualifiedName ?
That only works for modules and types - Luís mentioned that __traits(identifier) only returns the type, not the identifier. Consider: module foo; import std.traits; struct S { int n; } unittest { S s; // Prints "s.n" pragma(msg, s.n.stringof); // Prints "foo.S.n". pragma(msg, fullyQualifiedName!(s.n)); } As for getting the name s.n inside a template, I don't think that's currently possible. -- Simen
Jun 11 2018
parent reply Basile B. <b2.b2.b2.temp.temp gmx.com> writes:
On Monday, 11 June 2018 at 13:19:17 UTC, Simen Kjærås wrote:
 On Monday, 11 June 2018 at 12:59:01 UTC, Mike Franklin wrote:
 On Monday, 11 June 2018 at 12:38:33 UTC, Luís Marques wrote:
 Just to check. If you have a piece of code like 
 "foo.bar.baz", you can get the full hierarchy, for instance 
 with stringof:


      static assert(foo.bar.baz.stringof == "foo.bar.bar");
Are you looking for this: https://dlang.org/phobos/std_traits.html#fullyQualifiedName ?
That only works for modules and types - Luís mentioned that __traits(identifier) only returns the type, not the identifier. Consider: module foo; import std.traits; struct S { int n; } unittest { S s; // Prints "s.n" pragma(msg, s.n.stringof); // Prints "foo.S.n". pragma(msg, fullyQualifiedName!(s.n)); } As for getting the name s.n inside a template, I don't think that's currently possible. -- Simen
the FQN is working here but i find the first message a bit confuse. Not sure if this small runnable represents the issue ? --- module runnable; import std.stdio, std.traits; struct foo { struct bar { static int baz;} } template Test(alias arg) { pragma(msg, fullyQualifiedName!arg); } void main() { alias t = Test!(foo.bar.baz); // runnable.foo.bar.baz } ---
Jun 11 2018
parent reply =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Monday, 11 June 2018 at 13:39:22 UTC, Basile B. wrote:
 the FQN is working here but i find the first message a bit 
 confuse. Not sure if this small runnable represents the issue ?


 ---
 module runnable;

 import std.stdio, std.traits;

 struct foo {  struct bar { static int baz;} }

 template Test(alias arg)
 {
     pragma(msg, fullyQualifiedName!arg);
 }

 void main()
 {
     alias t = Test!(foo.bar.baz); // runnable.foo.bar.baz
 }
That gets the types foo, bar, baz. I wanted the identifiers. Something like this: struct Parent { Son son; } struct Son { int value; } void main() { Parent parent; alias t = Magic!(parent.son); // t is now parent (not Parent) }
Jun 11 2018
next sibling parent Basile B. <b2.b2.b2.temp.temp gmx.com> writes:
On Monday, 11 June 2018 at 13:47:41 UTC, Luís Marques wrote:
 On Monday, 11 June 2018 at 13:39:22 UTC, Basile B. wrote:
 the FQN is working here but i find the first message a bit 
 confuse. Not sure if this small runnable represents the issue ?


 ---
 module runnable;

 import std.stdio, std.traits;

 struct foo {  struct bar { static int baz;} }

 template Test(alias arg)
 {
     pragma(msg, fullyQualifiedName!arg);
 }

 void main()
 {
     alias t = Test!(foo.bar.baz); // runnable.foo.bar.baz
 }
That gets the types foo, bar, baz. I wanted the identifiers. Something like this: struct Parent { Son son; } struct Son { int value; } void main() { Parent parent; alias t = Magic!(parent.son); // t is now parent (not Parent) }
thanks that's clear now... it's indeed not possible --- module runnable; import std.stdio, std.traits; struct Foo {struct Bar{static int baz;} Bar bar;} Foo foo; template Test(alias arg) { // challenge: get "foo.bar.baz" here... } void main() { alias t = Test!(foo.bar.baz); } --- Maybe something with opDispatch but it sounds complicated at first glance.
Jun 11 2018
prev sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Monday, 11 June 2018 at 13:47:41 UTC, Luís Marques wrote:
 On Monday, 11 June 2018 at 13:39:22 UTC, Basile B. wrote:
 the FQN is working here but i find the first message a bit 
 confuse. Not sure if this small runnable represents the issue ?


 ---
 module runnable;

 import std.stdio, std.traits;

 struct foo {  struct bar { static int baz;} }

 template Test(alias arg)
 {
     pragma(msg, fullyQualifiedName!arg);
 }

 void main()
 {
     alias t = Test!(foo.bar.baz); // runnable.foo.bar.baz
 }
That gets the types foo, bar, baz. I wanted the identifiers. Something like this: struct Parent { Son son; } struct Son { int value; } void main() { Parent parent; alias t = Magic!(parent.son); // t is now parent (not Parent) }
this can only work unambiguously if Son is defined nested inside Parent. Otherwise it's lexical parent will be the module. So let's assume we have this structure struct Parent { double d; struct Son { int value; } Son son; } void main() { Parent p; p.d = 3.141; auto pfs = Magic(p.son); static assert(is(typeof(pfs) == Parent*)); assert(&pfs.son == &p.son); assert(pfs.d == 3.141); } auto Magic(S)(ref S s) { alias P = typeof(__traits(parent, S).init); enum s_index = () { foreach(i,m;[__traits(allMembers, P)]) { if (__traits(identifier, S) == m) { return i; } } assert(0); } (); enum s_offset = P.init.tupleof[s_index].offsetof; return cast(P*)( (cast(void*)&s) - s_offset); }
Jun 11 2018
parent =?UTF-8?B?THXDrXM=?= Marques <luis luismarques.eu> writes:
On Monday, 11 June 2018 at 20:49:01 UTC, Stefan Koch wrote:
 this can only work unambiguously if Son is defined nested 
 inside Parent.
Thanks for your solution. Unfortunately, it really doesn't cover my use case.
Jun 11 2018