digitalmars.D.learn - proper way to find if attribute present?
- Daniel Davidson (23/23) Oct 24 2013 enum Bar = "Bar";
- Jonathan M Davis (8/18) Oct 24 2013 You should probably use std.traits.functionAttributes:
- Adam D. Ruppe (3/4) Oct 24 2013 it doesn't list UDAs though.
- Dicebot (33/33) Oct 24 2013 I use this small helper in vibe.d:
- Adam D. Ruppe (33/34) Oct 24 2013 This function looks for annotations as identified by type.
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
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
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
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
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