Thread overview | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 01, 2018 Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
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? |
November 01, 2018 Re: Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Neia Neutuladh | 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 |
November 01, 2018 Re: Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Neia Neutuladh | 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);
}
}
```
|
November 01, 2018 Re: Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thu, 01 Nov 2018 11:35:27 -0700, Ali Çehreli wrote:
> 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
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.
|
November 01, 2018 Re: Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov | 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.
|
November 01, 2018 Re: Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Neia Neutuladh | 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: >> 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. Yes, it does :( > 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. |
November 02, 2018 Re: Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Neia Neutuladh | 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=19127 > What do you do to handle this? @Foo() int bar; instead of @Foo int bar; https://run.dlang.io/is/3USj6h |
November 02, 2018 Re: Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | On Fri, 02 Nov 2018 00:36:18 +0000, Nicholas Wilson wrote:
>> What do you do to handle this?
>
> @Foo() int bar;
>
> instead of
>
> @Foo int bar;
Right. And if you're offering a library with UDAs for other people to use?
|
November 02, 2018 Re: Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Neia Neutuladh | 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:
>>> What do you do to handle this?
>>
>> @Foo() int bar;
>>
>> instead of
>>
>> @Foo int bar;
>
> Right. And if you're offering a library with UDAs for other people to use?
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))
|
November 02, 2018 Re: Dealing with raw types as attributes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | 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.
|
Copyright © 1999-2021 by the D Language Foundation