Thread overview
How to get the UDAs for a function parameter correctly?
May 11, 2020
Heromyth
May 11, 2020
Adam D. Ruppe
May 11, 2020
Heromyth
May 11, 2020
I want to get the UDAs for for a function parameter. Here the test code and I got some errors:

source/app.d(29,33): Error: first argument is not a symbol
source/app.d(39,15): Error: template instance app.test!(ClassA) error instantiating

How can I fix this? Would this be a bug? Thanks.

=====================
import std.stdio;
import std.traits;
import std.meta;


struct Length {
    int a;
    int b;
}

class ClassA {
    void test(@Length(1, 9) int len, @Length(2, 4) int size) {
        writeln("It's OK");
    }

    void test(string name) {
        writeln("Can't be compiled");
    }
}

string test(T)() {
    string str;
    alias currentMembers = __traits(getOverloads, T, "test");

    static foreach(member; currentMembers) {{
        alias Params = Parameters!(member);
        static foreach(i; 0 .. Params.length)
        {{
            alias ThisParameter =  Params[i .. i + 1];
            static foreach(uda; __traits(getAttributes, ThisParameter)) {
                str ~= uda.stringof ~  "\n";
            }
        }}
    }}

    return str;
}

void main() {
    enum aa = test!(ClassA);
    writeln(aa);
}

May 11, 2020
On Monday, 11 May 2020 at 02:25:39 UTC, Heromyth wrote:
> I want to get the UDAs for for a function parameter. Here the test code and I got some errors:

I think my blog aside is one of the few if only write-ups on how to do this:

http://dpldocs.info/this-week-in-d/Blog.Posted_2019_02_11.html#how-to-get-uda-on-a-function-param


the library will not help much, you need to slice the parameters yourself. (It might work combine lib stuff with slice though, e.g. getUDA!(Parameters!F[1 .. 2]) maybe, i have never tried).

but this does work:

        static if(is(typeof(method) P == __parameters))
        foreach(idx, _; P) {{
		// alias for convenience later
                alias param = P[idx .. idx + 1]; // this slice is the trick
		// can get the identifier now
                string ident = __traits(identifier, param);
		// and the attributes
                foreach(attr; __traits(getAttributes, param))
			{}
	}}
May 11, 2020
On Monday, 11 May 2020 at 02:34:32 UTC, Adam D. Ruppe wrote:
> On Monday, 11 May 2020 at 02:25:39 UTC, Heromyth wrote:
>> I want to get the UDAs for for a function parameter. Here the test code and I got some errors:
>
> I think my blog aside is one of the few if only write-ups on how to do this:
>
> http://dpldocs.info/this-week-in-d/Blog.Posted_2019_02_11.html#how-to-get-uda-on-a-function-param
>
>
> the library will not help much, you need to slice the parameters yourself. (It might work combine lib stuff with slice though, e.g. getUDA!(Parameters!F[1 .. 2]) maybe, i have never tried).
>
> but this does work:
>
>         static if(is(typeof(method) P == __parameters))
>         foreach(idx, _; P) {{
> 		// alias for convenience later
>                 alias param = P[idx .. idx + 1]; // this slice is the trick
> 		// can get the identifier now
>                 string ident = __traits(identifier, param);
> 		// and the attributes
>                 foreach(attr; __traits(getAttributes, param))
> 			{}
> 	}}

That's great! It should use
   static if(is(typeof(method) P == __parameters))
to get all the parameters instead of using:
   alias Params = Parameters!(member);


Here is the adjusted code:
=================================
import std.stdio;
import std.traits;
import std.meta;

struct Length {
    int a;
    int b;
}

class ClassA {
    void test(@Length(1, 9) int len, @Length(2, 4) int size) {
        writeln("It's OK");
    }

    void test(string name, @Length(3, 5) int len) {
        writeln("Works now");
    }

    void test() {
    }
}

string test(T)() {
    string str;
    alias currentMembers = __traits(getOverloads, T, "test");

    static foreach(member; currentMembers) {{
        static if(is(typeof(member) Params == __parameters)) {
            static foreach(i, _; Params)
            {{
                alias ThisParameter =  Params[i .. i + 1];
                static foreach(uda; __traits(getAttributes, ThisParameter)) {
                    str ~= uda.stringof ~  "\n";
                }
            }}
        }
    }}

    return str;
}

void main() {
    enum aa = test!(ClassA);
    writeln(aa);
}