www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - proper way to find if attribute present?

reply "Daniel Davidson" <nospam spam.com> writes:
enum Bar = "Bar";
 ("Foo")  Bar int x;
pragma(msg, __traits(getAttributes, x));

This prints: tuple("Foo", "Bar")

How do you run code only if "Bar" is associated with a symbol 
like x?
I was hoping something like this:
pragma(msg, hasAnnotation!(x, Bar));

Where getAnnotation from 
(http://forum.dlang.org/thread/jxbdiwyyxwnmmybiqvyq forum.dlang.org)
was written as:

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;
}


I am missing how this can be used.

Thanks
Dan
Oct 24 2013
next sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Thursday, October 24, 2013 18:22:43 Daniel Davidson wrote:
 enum Bar = "Bar";
  ("Foo")  Bar int x;
 pragma(msg, __traits(getAttributes, x));
 
 This prints: tuple("Foo", "Bar")
 
 How do you run code only if "Bar" is associated with a symbol
 like x?
 I was hoping something like this:
 pragma(msg, hasAnnotation!(x, Bar));
You should probably use std.traits.functionAttributes: And in general, you should favor using std.traits over __traits. Ideally, no code outside of the standard library would need to use __traits. That's not currently the case unfortunately, but it is the case that std.traits has much of what you need for anything involving static introspection. - Jonathan M Davis
Oct 24 2013
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 24 October 2013 at 17:36:42 UTC, Jonathan M Davis 
wrote:
 You should probably use std.traits.functionAttributes:
it doesn't list UDAs though.
Oct 24 2013
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
I use this small helper in vibe.d:

=======================
template extractUda(UDA, alias Symbol)
{
     import std.typetuple : TypeTuple;

     private alias TypeTuple!(__traits(getAttributes, Symbol)) 
udaTuple;

     private template extract(list...)
     {
         static if (!list.length)
             enum extract = null;
         else {
             static assert (!is(list[0] == UDA), "extractUda is 
designed to look up values, not types");

             static if (is(typeof(list[0]) == UDA))
                 enum extract = list[0];
             else
                 enum extract = extract!(list[1..$]);
         }
     }

     enum extractUda = extract!udaTuple;
}
=======================

Used like this:
=======================
 Bar("value") void foo();

enum uda = extractUda!(Bar, foo);

static if (is(typeof(uda) != typeof(null)))
     static assert (uda == Bar("value"));
=======================

It is far from perfection but can serve as a starting point for 
more complete implementation (though I have kept certain 
limitations intentionally)
Oct 24 2013
prev sibling parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 24 October 2013 at 16:22:44 UTC, Daniel Davidson 
wrote:
 template hasAnnotation(alias f, Attr) {
This function looks for annotations as identified by type. Instead of using a plain string, you should make them some kind of struct: struct MyAnnotation { string value; } Then you attach it like this: MyAnnotation("some value") void foo() {} Then you'll be able to get it with the other two functions in there: static if(hasValueAnnotation!(foo, MyAnnotation)) { pragma(msg, getAnnotation!(foo, MyAnnotation)); // prints MyAnnotation("some value") // or you can fetch it into a variable: MyAnnotation a = getAnnotation!(foo, MyAnnotation); assert(a.value == "some value"); } It is possible to use plain string in place of the MyAnnotation struct: ("some value") void foo() {} static if(hasValueAnnotation!(foo, string)) { pragma(msg, getAnnotation!(foo, string)); // prints MyAnnotation("some value") // or you can fetch it into a variable: string a = getAnnotation!(foo, string); assert(a == "some value"); } But that isn't as reliable across modules because strings might be reused by anyone. A struct would always have a unique identifier - the struct name, which can be disambiguated by module.
Oct 24 2013