Thread overview
need this for name of type string
Sep 10
Alex
September 10
Hi,

following coding is throwing compiler error:
  need this for name of type string

The error disappears if I delete method0.
My gut feeling is, this is a compiler bug?

---
class C
{
    static this()
    {
        getT!(typeof(this))();
    }

    @Foo void method0(){}

    @Foo("abc") void method1(){}
}

struct Foo
{
    string name;
}

void getT(T)()
{
    import std.traits: hasUDA, getUDAs;

    static foreach(fieldName; __traits(allMembers, T))
    {
        static if (hasUDA!(__traits(getMember, T, fieldName), Foo))
        {
            pragma(msg, getUDAs!(__traits(getMember, T, fieldName), Foo)[0].name);
        }
    }
}

void main(){}
---

Kind regards
André
September 10
On Tuesday, 10 September 2019 at 10:32:29 UTC, Andre Pany wrote:
> Hi,
>
> following coding is throwing compiler error:
>   need this for name of type string
>
> The error disappears if I delete method0.
> My gut feeling is, this is a compiler bug?
>
> ---
> class C
> {
>     static this()
>     {
>         getT!(typeof(this))();
>     }
>
>     @Foo void method0(){}
>
>     @Foo("abc") void method1(){}
> }
>
> struct Foo
> {
>     string name;
> }
>
> void getT(T)()
> {
>     import std.traits: hasUDA, getUDAs;
>
>     static foreach(fieldName; __traits(allMembers, T))
>     {
>         static if (hasUDA!(__traits(getMember, T, fieldName), Foo))
>         {
>             pragma(msg, getUDAs!(__traits(getMember, T, fieldName), Foo)[0].name);
>         }
>     }
> }
>
> void main(){}
> ---
>
> Kind regards
> André

Don't think so. In case of @Foo, you don't instantiate an object. Therefore, name cannot exist. So... in this case, the UDA is a type, not an object you can query for a name.
It's more the like the example with SimpleAttr on the help page [1], I think.

[1] https://dlang.org/library/std/traits/get_ud_as.html
September 10
On 09/10/2019 03:32 AM, Andre Pany wrote:

>      @Foo void method0(){}
>
>      @Foo("abc") void method1(){}

The UDA syntax allows both types and an objects. method0 uses Foo type and method1 uses a Foo object. So, if your API allows both, your code that deals with UDA must account for both.

The simplest solution here is to have method0 take an object as well:

  @Foo() void method0(){}

If you want to allow for both, the UDA code must change similar to the following:

    static foreach(fieldName; __traits(allMembers, T))
    {
        static if (hasUDA!(__traits(getMember, T, fieldName), Foo))
        {
          static if (is (getUDAs!(__traits(getMember, T, fieldName), Foo)[0])) {
            // The UDA is the type Foo
            pragma(msg, "Default Foo string: ", Foo.init.name);

          } else {
            // The UDA is a Foo object
            pragma(msg, "Special Foo string: ", getUDAs!(__traits(getMember, T, fieldName), Foo)[0].name);
          }
        }
    }

Ali

September 10
On Tuesday, 10 September 2019 at 11:20:03 UTC, Ali Çehreli wrote:
> On 09/10/2019 03:32 AM, Andre Pany wrote:
>
> >      [...]
>
> The UDA syntax allows both types and an objects. method0 uses Foo type and method1 uses a Foo object. So, if your API allows both, your code that deals with UDA must account for both.
>
> [...]

Fantastic! Thanks a lot for the solution.

Kind regards
André