Thread overview
Identifier hierarchy
Jun 11, 2018
Luís Marques
Jun 11, 2018
Mike Franklin
Jun 11, 2018
Simen Kjærås
Jun 11, 2018
Basile B.
Jun 11, 2018
Luís Marques
Jun 11, 2018
Basile B.
Jun 11, 2018
Stefan Koch
Jun 11, 2018
Luís Marques
June 11, 2018
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?
June 11, 2018
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

June 11, 2018
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
June 11, 2018
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
}
---
June 11, 2018
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)
}

June 11, 2018
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.
June 11, 2018
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);
}



June 11, 2018
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.