Thread overview
UDA usage
Oct 05, 2013
Matt Soucy
Oct 05, 2013
Adam D. Ruppe
Oct 05, 2013
Matt Soucy
Oct 08, 2013
Matt Soucy
Oct 08, 2013
Adam D. Ruppe
October 05, 2013
So, I was away from active D development for a while, and I'm having
trouble finding info about how to use UDAs. I can see the basics, like
how to apply a UDA to a symbol, but now how to do specific things, like:
* Check to see if a specific attribute exists
* Check to see if an attribute of a specific type exists, something like:
@Foo('a') int x;
enum hasAnyFoo = __traits(hasAttributeOfType, Foo, x);
* Create a function that can only be called if the first argument has a
UDA of a specific type

Are any of these doable?
Thank you,
-Matt Soucy



October 05, 2013
On Saturday, 5 October 2013 at 02:51:21 UTC, Matt Soucy wrote:
> * Check to see if a specific attribute exists
> * Check to see if an attribute of a specific type exists, something like:

The helper functions from my web.d might help:

// checks to see if it has one of a type
// static if(hasAnnotation!(func, Foo)) { has @Foo }
// use if Foo is a simple enum.
template hasAnnotation(alias f, Attr) {
	bool helper() {
		foreach(attr; __traits(getAttributes, f))
			static if(is(attr == Attr) || is(typeof(attr) == Attr))
				return true;
		return false;

	}
	enum bool hasAnnotation = helper;
}

/// checks to see if it has an annotation with a value e.g. @Something(10)
template hasValueAnnotation(alias f, Attr) {
	bool helper() {
		foreach(attr; __traits(getAttributes, f))
			static if(is(typeof(attr) == Attr))
				return true;
		return false;

	}
	enum bool hasValueAnnotation = helper;
}

/// gets the thing you checked for above. so getAnnotation!(Func, Something) returns Something(10) (if Something is as struct)
template getAnnotation(alias f, Attr) if(hasValueAnnotation!(f, Attr)) {
	auto helper() {
		foreach(attr; __traits(getAttributes, f))
			static if(is(typeof(attr) == Attr))
				return attr;
		assert(0);
	}

	enum getAnnotation = helper;
}


> * Create a function that can only be called if the first argument has a
> UDA of a specific type

Since the UDA is only available at compile time, you can't do that without some kind of template.
October 05, 2013
On 10/04/2013 11:04 PM, Adam D. Ruppe wrote:
> On Saturday, 5 October 2013 at 02:51:21 UTC, Matt Soucy wrote:
>> * Check to see if a specific attribute exists
>> * Check to see if an attribute of a specific type exists, something like:
> 
> The helper functions from my web.d might help:
> 
> // checks to see if it has one of a type
> // static if(hasAnnotation!(func, Foo)) { has @Foo }
> // use if Foo is a simple enum.
> template hasAnnotation(alias f, Attr) {
>     bool helper() {
>         foreach(attr; __traits(getAttributes, f))
>             static if(is(attr == Attr) || is(typeof(attr) == Attr))
>                 return true;
>         return false;
> 
>     }
>     enum bool hasAnnotation = helper;
> }
> 
> /// checks to see if it has an annotation with a value e.g. @Something(10)
> template hasValueAnnotation(alias f, Attr) {
>     bool helper() {
>         foreach(attr; __traits(getAttributes, f))
>             static if(is(typeof(attr) == Attr))
>                 return true;
>         return false;
> 
>     }
>     enum bool hasValueAnnotation = helper;
> }
> 
> /// gets the thing you checked for above. so getAnnotation!(Func,
> Something) returns Something(10) (if Something is as struct)
> template getAnnotation(alias f, Attr) if(hasValueAnnotation!(f, Attr)) {
>     auto helper() {
>         foreach(attr; __traits(getAttributes, f))
>             static if(is(typeof(attr) == Attr))
>                 return attr;
>         assert(0);
>     }
> 
>     enum getAnnotation = helper;
> }
> 
> 

Nice, thank you. These are really helpful!

>> * Create a function that can only be called if the first argument has a UDA of a specific type
> 
> Since the UDA is only available at compile time, you can't do that without some kind of template.

Using the above tools I got what I wanted, so I'm satisfied for now.
Thank you, though!
-Matt Soucy




October 08, 2013
On 10/04/2013 11:50 PM, Matt Soucy wrote:
> On 10/04/2013 11:04 PM, Adam D. Ruppe wrote:
>> On Saturday, 5 October 2013 at 02:51:21 UTC, Matt Soucy wrote:
>>> * Check to see if a specific attribute exists
>>> * Check to see if an attribute of a specific type exists, something like:
>>
>> The helper functions from my web.d might help:
>>
>> // checks to see if it has one of a type
>> // static if(hasAnnotation!(func, Foo)) { has @Foo }
>> // use if Foo is a simple enum.
>> template hasAnnotation(alias f, Attr) {
>>     bool helper() {
>>         foreach(attr; __traits(getAttributes, f))
>>             static if(is(attr == Attr) || is(typeof(attr) == Attr))
>>                 return true;
>>         return false;
>>
>>     }
>>     enum bool hasAnnotation = helper;
>> }
>>
>> /// checks to see if it has an annotation with a value e.g. @Something(10)
>> template hasValueAnnotation(alias f, Attr) {
>>     bool helper() {
>>         foreach(attr; __traits(getAttributes, f))
>>             static if(is(typeof(attr) == Attr))
>>                 return true;
>>         return false;
>>
>>     }
>>     enum bool hasValueAnnotation = helper;
>> }
>>
>> /// gets the thing you checked for above. so getAnnotation!(Func,
>> Something) returns Something(10) (if Something is as struct)
>> template getAnnotation(alias f, Attr) if(hasValueAnnotation!(f, Attr)) {
>>     auto helper() {
>>         foreach(attr; __traits(getAttributes, f))
>>             static if(is(typeof(attr) == Attr))
>>                 return attr;
>>         assert(0);
>>     }
>>
>>     enum getAnnotation = helper;
>> }
>>
>>
> 
> Nice, thank you. These are really helpful!
> 
>>> * Create a function that can only be called if the first argument has a UDA of a specific type
>>
>> Since the UDA is only available at compile time, you can't do that without some kind of template.
> 
> Using the above tools I got what I wanted, so I'm satisfied for now.
> Thank you, though!
> -Matt Soucy
> 
> 
Update on this - unfortunately, I discovered that this doesn't seem to work for any members, due to requiring a specific "this". I can't quite figure out why though...

-- 
Matt Soucy
http://msoucy.me/



October 08, 2013
On Tuesday, 8 October 2013 at 20:59:04 UTC, Matt Soucy wrote:
> Update on this - unfortunately, I discovered that this doesn't seem to work for any members, due to requiring a specific "this". I can't quite figure out why though...

Try adding static to the helper functions in the templates. I just did that and this worked:

struct Whoa {
        int a;
}

class Foo {
        @lol void argh() {}
        @Whoa(12) int keanu;
}

void main() {
        pragma(msg, hasAnnotation!(Foo.argh, lol));
        pragma(msg, getAnnotation!(Foo.keanu, Whoa));
}


~$ dmd test34
true
Whoa(12)




The change to get it to compile was just this:

template hasValueAnnotation(alias f, Attr) {
        static bool helper() { // added static


and so on for all three of the helper functions, just make them all static.