digitalmars.D.learn - Dealing with raw types as attributes
- Neia Neutuladh (34/34) Nov 01 2018 The spec says that a user-defined attribute must be an expression, but D...
- =?UTF-8?Q?Ali_=c3=87ehreli?= (4/12) Nov 01 2018 That would work with hasUDA(). I have an example here:
- Neia Neutuladh (7/20) Nov 01 2018 That lets me test for presence, nothing more. While that's useful, I
- Stanislav Blinov (21/40) Nov 01 2018 Check if an UDA is a type?.. As in, not just `is(uda == Foo)`,
- Neia Neutuladh (5/7) Nov 01 2018 Which works, but generally makes things more complex in code that's
- Stanislav Blinov (14/23) Nov 01 2018 Yes, it does :(
- Nicholas Wilson (8/11) Nov 01 2018 Indeed UDA are odd beasts:
- Neia Neutuladh (2/9) Nov 01 2018 Right. And if you're offering a library with UDAs for other people to us...
- Nicholas Wilson (14/24) Nov 01 2018 I mean I suppose if you really wanted to avoid the parentheses,
- Neia Neutuladh (4/10) Nov 01 2018 Which, again, only tests for presence, when I want to check for presence...
- Nicholas Wilson (10/21) Nov 01 2018 template GetMeTheValue(value...) if(value.length == 1)
- Kagamin (3/7) Nov 02 2018 IIRC symbol reference is a primary expression.
The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } Foo int bar; `bar` has the *type* Foo as an attribute. It's not an *instance* of Foo. So if I try to look at the UDAs: static foreach (uda; __traits(getAttributes, bar)) { static if (is(typeof(uda) == Foo)) { pragma(msg, "bar is Foo"); } } That just doesn't work; typeof(Foo) isn't anything, so is(typeof(Foo) == Foo) is false. I can change my code to read `static if (is(uda == Foo))`. But that obviously fails: Foo("customName") int bar2; What do you do to handle this? My current workaround is to make the attribute into a struct instance and use opCall in lieu of constructors: struct _Foo { string name; _Foo opCall(string name) { _Foo f; f.name = name; return f; } } enum _Foo Foo = _Foo.init; Now I can use `static if (is(typeof(uda) == _Foo))` and it always works. But are there better options? Any obvious flaws?
Nov 01 2018
On 11/01/2018 09:14 AM, Neia Neutuladh wrote:The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } Foo int bar; `bar` has the *type* Foo as an attribute. It's not an *instance* of Foo. So if I try to look at the UDAs:That would work with hasUDA(). I have an example here: http://ddili.org/ders/d.en/uda.html Ali
Nov 01 2018
On Thu, 01 Nov 2018 11:35:27 -0700, Ali Çehreli wrote:On 11/01/2018 09:14 AM, Neia Neutuladh wrote:That lets me test for presence, nothing more. While that's useful, I usually have a UDA struct whose fields I need to access. std.traits.getUDAs doesn't hide the difference between Foo and Foo(), so that's also not an option. I could use a customized version of that that replaces Type with Type.init, and that's a reasonable choice when I know other people aren't going to deal with that annotation type.The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } Foo int bar; `bar` has the *type* Foo as an attribute. It's not an *instance* of Foo. So if I try to look at the UDAs:That would work with hasUDA(). I have an example here: http://ddili.org/ders/d.en/uda.html
Nov 01 2018
On Thursday, 1 November 2018 at 16:14:45 UTC, Neia Neutuladh wrote:The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } Foo int bar; `bar` has the *type* Foo as an attribute. It's not an *instance* of Foo. So if I try to look at the UDAs: static foreach (uda; __traits(getAttributes, bar)) { static if (is(typeof(uda) == Foo)) { pragma(msg, "bar is Foo"); } } That just doesn't work; typeof(Foo) isn't anything, so is(typeof(Foo) == Foo) is false. I can change my code to read `static if (is(uda == Foo))`. But that obviously fails: Foo("customName") int bar2; What do you do to handle this?Check if an UDA is a type?.. As in, not just `is(uda == Foo)`, but simply `is(uda)`: ``` struct Foo { string name = "unknown"; } Foo string Foo("hello") int bar; static foreach (uda; __traits(getAttributes, bar)) { static if (is(uda)) { // if `uda` is a type... static if (is(uda == Foo)) { pragma(msg, "bar is Foo!!!"); } else { pragma(msg, "bar is "~uda.stringof); } } else { // if `uda` is not a type... pragma(msg, "bar is "~uda.stringof); } } ```
Nov 01 2018
On Thu, 01 Nov 2018 20:01:51 +0000, Stanislav Blinov wrote:Check if an UDA is a type?.. As in, not just `is(uda == Foo)`, but simply `is(uda)`:Which works, but generally makes things more complex in code that's already pretty deeply nested. It's also something I have to worry about every time I do the static foreach to get UDAs, in the cases where that's more than once.
Nov 01 2018
On Thursday, 1 November 2018 at 20:33:10 UTC, Neia Neutuladh wrote:On Thu, 01 Nov 2018 20:01:51 +0000, Stanislav Blinov wrote:Yes, it does :(Check if an UDA is a type?.. As in, not just `is(uda == Foo)`, but simply `is(uda)`:Which works, but generally makes things more complex in code that's already pretty deeply nested. It's also something I have to worry about every time I do the static foreach to get UDAs, in the cases where that's more than once.I could use a customized version of [getUDAs] that replaces Type with Type.init, and that's a reasonable choice...That can't be generic, as you can have UDAs that don't have an .init: enum XXX; XXX int bar; static foreach (uda; __traits(getAttributes, bar)) { static if (is(uda == XXX)) { pragma(msg, "bar is XXX"); } } ...but so long as you can live without such UDAs, I guess it could work.
Nov 01 2018
On Thursday, 1 November 2018 at 16:14:45 UTC, Neia Neutuladh wrote:The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs:Indeed UDA are odd beasts: https://issues.dlang.org/show_bug.cgi?id=19127What do you do to handle this?Foo() int bar; instead of Foo int bar; https://run.dlang.io/is/3USj6h
Nov 01 2018
On Fri, 02 Nov 2018 00:36:18 +0000, Nicholas Wilson wrote:Right. And if you're offering a library with UDAs for other people to use?What do you do to handle this?Foo() int bar; instead of Foo int bar;
Nov 01 2018
On Friday, 2 November 2018 at 03:13:19 UTC, Neia Neutuladh wrote:On Fri, 02 Nov 2018 00:36:18 +0000, Nicholas Wilson wrote:I mean I suppose if you really wanted to avoid the parentheses, you could do static foreach (uda; __traits(getAttributes, bar)) { static if (is(typeof(uda.init) == Foo) { pragma(msg, "bar is Foo"); } } By noting that all (interesting for the purpose of UDA's i.e. not void) types have a .init or you could do static if (is(typeof(uda) == Foo) || is(uda == Foo))Right. And if you're offering a library with UDAs for other people to use?What do you do to handle this?Foo() int bar; instead of Foo int bar;
Nov 01 2018
On Fri, 02 Nov 2018 04:01:00 +0000, Nicholas Wilson wrote:By noting that all (interesting for the purpose of UDA's i.e. not void) types have a .init or you could do static if (is(typeof(uda) == Foo) || is(uda == Foo))Which, again, only tests for presence, when I want to check for presence *and* get the value, which should be Foo.init if the person supplied the raw type.
Nov 01 2018
On Friday, 2 November 2018 at 04:18:47 UTC, Neia Neutuladh wrote:On Fri, 02 Nov 2018 04:01:00 +0000, Nicholas Wilson wrote:template GetMeTheValue(value...) if(value.length == 1) { static if (is(typeof(value[0].init == value[0]) // A type enum GetMeTheValue = value[0].init; else enum GetMeTheValue = value[0]; } ... static if (is(typeof(GetMeTheValue!uda) == Foo)By noting that all (interesting for the purpose of UDA's i.e. not void) types have a .init or you could do static if (is(typeof(uda) == Foo) || is(uda == Foo))Which, again, only tests for presence, when I want to check for presence *and* get the value, which should be Foo.init if the person supplied the raw type.
Nov 01 2018
On Thursday, 1 November 2018 at 16:14:45 UTC, Neia Neutuladh wrote:The spec says that a user-defined attribute must be an expression, but DMD accepts a wide range of things as UDAs: struct Foo { string name = "unknown"; } Foo int bar;IIRC symbol reference is a primary expression.
Nov 02 2018