www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Function parameters UDAs

reply Radu <void null.pt> writes:
Looks like that there is no easy way to extract a function 
parameters UDA list.

The following:
```
import std.traits;

struct s { string foo; }
void foo( s("aaa") int a, bool x);

void main()
{
     alias P = Parameters!foo;
     enum udas = __traits(getAttributes, P);
     pragma(msg, udas);
}
```
will print `tuple(s("aaa"))`

but if you change `foo` to `void foo(int a,  s("aaa") bool x);`

you get `Error: first argument is not a symbol`

Is this a current limitation or I'm using the wrong approach?
Nov 14 2018
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Wednesday, 14 November 2018 at 16:28:19 UTC, Radu wrote:
 Looks like that there is no easy way to extract a function 
 parameters UDA list.
Indeed, the only way I can find is kinda crazy: --- void foo(int f, ("test") string s) {} void main() { static if(is(typeof(foo) Params == __parameters)) pragma(msg, __traits(getAttributes, Params[1..2])); // get the second param } --- So, the process is: 1) alias the params with the static if + is() statement (this is what std.traits.Parameters does internally) 2) slice the params! using params[0] will not work, but params[0 .. 1] will. 3) get the attributes using the language function
Nov 14 2018
next sibling parent Radu <void null.pt> writes:
On Wednesday, 14 November 2018 at 18:05:55 UTC, Adam D. Ruppe 
wrote:
 On Wednesday, 14 November 2018 at 16:28:19 UTC, Radu wrote:
 Looks like that there is no easy way to extract a function 
 parameters UDA list.
Indeed, the only way I can find is kinda crazy: --- void foo(int f, ("test") string s) {} void main() { static if(is(typeof(foo) Params == __parameters)) pragma(msg, __traits(getAttributes, Params[1..2])); // get the second param } --- So, the process is: 1) alias the params with the static if + is() statement (this is what std.traits.Parameters does internally) 2) slice the params! using params[0] will not work, but params[0 .. 1] will. 3) get the attributes using the language function
Yes, that does the trick, thanks!
Nov 14 2018
prev sibling parent reply Johannes Loher <johannes.loher fg4f.de> writes:
On Wednesday, 14 November 2018 at 18:05:55 UTC, Adam D. Ruppe 
wrote:
 On Wednesday, 14 November 2018 at 16:28:19 UTC, Radu wrote:
 Looks like that there is no easy way to extract a function 
 parameters UDA list.
Indeed, the only way I can find is kinda crazy: --- void foo(int f, ("test") string s) {} void main() { static if(is(typeof(foo) Params == __parameters)) pragma(msg, __traits(getAttributes, Params[1..2])); // get the second param } --- So, the process is: 1) alias the params with the static if + is() statement (this is what std.traits.Parameters does internally) 2) slice the params! using params[0] will not work, but params[0 .. 1] will. 3) get the attributes using the language function
Has anybody come up with a better solution yet? And why does __traits(getAttributes, Parameters!foo[0]) not work in the first place? I am asking because I ran into a problem which does not seem solvable to me using the above workaround: I would like to iterate over all parameters of a function using static foreach and then process each parameter's UDAs. But by using static foreach on the parameter tuple, slicing it is not possible anymore, so the suggested workaround does not work in this case :( The error does not appear if all parameters of the function are symbols (e.g. structs), but it still does not work as expected because the UDAs simply get dropped when iterating over the parameter tuple. Here is an example: import std; struct Test {} void foo( (1) Test x) { } void main() { alias Params = Parameters!foo; pragma(msg, Params); static foreach(P; Params) { pragma(msg, P); static foreach(uda; __traits(getAttributes, P)) { pragma(msg, uda); } } } This prints ( (1) Test) Test but I would expect it to print something like ( (1) Test) (1) Test (1)
Jun 10 2019
parent ag0aep6g <anonymous example.com> writes:
On 11.06.19 01:12, Johannes Loher wrote:
 I would like to iterate over all parameters of a function using static 
 foreach and then process each parameter's UDAs. But by using static 
 foreach on the parameter tuple, slicing it is not possible anymore, so 
 the suggested workaround does not work in this case :(
The workaround is to work with 1-length slices of your parameter sequence instead of elements. You can still do that. You just can't `foreach` over the parameters directly. Instead, iterate with an index and use it to get slices: ----- import std; struct Test {} void foo( (1) Test x, (2) (3) float y) { } void main() { alias Params = Parameters!foo; pragma(msg, Params); static foreach(i; 0 .. Params.length) {{ alias P = Params[i .. i + 1]; pragma(msg, P); static foreach(uda; __traits(getAttributes, P)) { pragma(msg, uda); } }} } ---- Prints: ---- ( (1) Test, (tuple(2), tuple(3)) float) ( (1) Test) 1 ( (tuple(2), tuple(3)) float) 2 3 ----
Jun 10 2019
prev sibling parent reply Machine Code <jckj33 gmail.com> writes:
On Wednesday, 14 November 2018 at 16:28:19 UTC, Radu wrote:
 Looks like that there is no easy way to extract a function 
 parameters UDA list.

 The following:
 ```
 import std.traits;

 struct s { string foo; }
 void foo( s("aaa") int a, bool x);

 void main()
 {
     alias P = Parameters!foo;
     enum udas = __traits(getAttributes, P);
     pragma(msg, udas);
 }
 ```
 will print `tuple(s("aaa"))`

 but if you change `foo` to `void foo(int a,  s("aaa") bool x);`

 you get `Error: first argument is not a symbol`

 Is this a current limitation or I'm using the wrong approach?
I also, quite disappointed how UDAs doesn't work with enums. I end up using struct + enum to simulate that, sometimes it's quite a work.
Jun 10 2019
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 11 June 2019 at 02:04:13 UTC, Machine Code wrote:
 I also, quite disappointed how UDAs doesn't work with enums. I 
 end up using struct + enum to simulate that, sometimes it's 
 quite a work.
They do now... struct foo {} enum Foo { foo a } void main() { foreach(item; __traits(allMembers, Foo)) pragma(msg, __traits(getAttributes, __traits(getMember, Foo, item))); }
Jun 10 2019
parent Machine Code <jckj33 gmail.com> writes:
On Tuesday, 11 June 2019 at 02:24:49 UTC, Adam D. Ruppe wrote:
 On Tuesday, 11 June 2019 at 02:04:13 UTC, Machine Code wrote:
 I also, quite disappointed how UDAs doesn't work with enums. I 
 end up using struct + enum to simulate that, sometimes it's 
 quite a work.
They do now... struct foo {} enum Foo { foo a } void main() { foreach(item; __traits(allMembers, Foo)) pragma(msg, __traits(getAttributes, __traits(getMember, Foo, item))); }
Awesome! It came out and I didn't notice.
Jun 10 2019