www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - UDA status

reply "simendsjo" <simendsjo gmail.com> writes:
I've been trying UDAs today, but I'm hitting roadblocks all the 
time..
For instance:
      (10) struct A;
     pragma(msg, __traits(getAttributes, A)); // Empty
      (10) struct B {}
     pragma(msg, __traits(getAttributes, B)); // tuple(10)

I've encountered several other things that has been difficult, 
especially when combining values and types and trying to 
manipulate these (might be some Tuple related stuff I'm not 
getting though).

Are there many outstanding issues regarding UDAs? Many fixes in 
2.063?
I cannot find many tickets regarding UDAs in bugzilla.

Seems std.traits isn't updated for UDAs either.

So what's the status of UDAs? Anyone have experience using them 
yet?
Mar 11 2013
parent reply "simendsjo" <simendsjo gmail.com> writes:
On Monday, 11 March 2013 at 19:03:49 UTC, simendsjo wrote:
 I've been trying UDAs today, but I'm hitting roadblocks all the 
 time..
 For instance:
      (10) struct A;
     pragma(msg, __traits(getAttributes, A)); // Empty
      (10) struct B {}
     pragma(msg, __traits(getAttributes, B)); // tuple(10)

 I've encountered several other things that has been difficult, 
 especially when combining values and types and trying to 
 manipulate these (might be some Tuple related stuff I'm not 
 getting though).

 Are there many outstanding issues regarding UDAs? Many fixes in 
 2.063?
 I cannot find many tickets regarding UDAs in bugzilla.

 Seems std.traits isn't updated for UDAs either.

 So what's the status of UDAs? Anyone have experience using them 
 yet?
Some update.. Using a custom Tuple(T...) makes things a bit smoother. Here's my first working test with two templates: hasAttr to see if an attribute exists, and attrOfType to get all attributes matching a type (not sure if I should include values..) module uda; debug(UDA) import std.stdio; template attrOfType(alias OfType, alias Source) { alias _attrOfType!(OfType, AttributeTuple!Source) attrOfType; } template hasAttr(alias S, alias A) { bool _hasAttr() { version(none) { debug(UDA) pragma(msg, "hasAttr(", TypeOf!S, ", ", A, ")"); debug(UDA) pragma(msg, " attributes: ", __traits(getAttributes, TypeOf!S)); } foreach(attr; __traits(getAttributes, TypeOf!S)) { static if(isSameAttribute!(attr, A)) return true; } return false; } enum hasAttr = _hasAttr(); } unittest { struct A1 { int i; } struct NoAttr {} assert(!hasAttr!(NoAttr, A1)); NoAttr noAttr; assert(!hasAttr!(noAttr, A1)); A1 struct AttrType {} assert( hasAttr!(AttrType, A1)); AttrType attrType; assert( hasAttr!(attrType, A1)); A1(10) struct AttrValue {} assert( hasAttr!(AttrValue, A1(10))); assert(!hasAttr!(AttrValue, A1(0))); assert(!hasAttr!(AttrValue, A1)); AttrValue attrValue; assert( hasAttr!(attrValue, A1(10))); assert(!hasAttr!(attrValue, A1(0))); assert(!hasAttr!(attrValue, A1)); (10) struct AttrPrimitive {} assert( hasAttr!(AttrPrimitive, 10)); } //////////////////////////////////////////// //////////////////////////////////////////// /// /// PRIVATE /// //////////////////////////////////////////// //////////////////////////////////////////// private: template isInstanceOrLiteral(alias S) { enum isInstanceOrLiteral = __traits(compiles, typeof(S)); } template isInstanceOrLiteral(T) { enum isInstanceOrLiteral = false; } unittest { assert(!isInstanceOrLiteral!int); int i; assert( isInstanceOrLiteral!i); assert( isInstanceOrLiteral!10); struct S {} assert(!isInstanceOrLiteral!S); S s; assert( isInstanceOrLiteral!s); class C {} assert(!isInstanceOrLiteral!C); C c; assert(isInstanceOrLiteral!c); } template TypeOf(alias S) { static if(isInstanceOrLiteral!S) alias typeof(S) TypeOf; else alias S TypeOf; } unittest { struct S {} assert( is(TypeOf!S == S)); S s; assert( is(TypeOf!s == S)); } template Tuple(T...) { alias T Tuple; } template AttributeTuple(alias T) { alias Tuple!(__traits(getAttributes, T)) AttributeTuple; } unittest { struct NoAttrs {} assert( AttributeTuple!(NoAttrs).length == 0); struct A1 {} A1 struct S1 {} assert( AttributeTuple!(S1).length == 1); assert( is(AttributeTuple!(S1)[0] == A1)); (10, "aoeu", A1) struct S2 {} assert( AttributeTuple!(S2).length == 3); assert( AttributeTuple!(S2)[0] == 10); assert( AttributeTuple!(S2)[1] == "aoeu"); assert( is(AttributeTuple!(S2)[2] == A1)); struct A2 { int i; } A2 A2(10) struct S3 {} assert( AttributeTuple!(S3).length == 2); assert( is(AttributeTuple!(S3)[0] == A2)); assert(!is(AttributeTuple!(S3)[1] == A2)); // static type - not equal assert( AttributeTuple!(S3)[1] == A2(10)); } template isSameAttribute(alias A, alias B) { static if(isInstanceOrLiteral!A && isInstanceOrLiteral!B) static if(__traits(compiles, A == B)) enum isSameAttribute = A == B; else enum isSameAttribute = false; else static if(!isInstanceOrLiteral!A && !isInstanceOrLiteral!B && is(A == B)) enum isSameAttribute = true; else enum isSameAttribute = false; } template isSameAttribute(A, B) { enum isSameAttribute = is(A == B); } template isSameAttribute(alias A, B) { enum isSameAttribute = false; } template isSameAttribute(A, alias B) { enum isSameAttribute = false; } unittest { assert( isSameAttribute!(1, 1)); assert(!isSameAttribute!(1, 2)); assert( isSameAttribute!("aoeu", "aoeu")); assert(!isSameAttribute!("aoeu", "qwerty")); assert( isSameAttribute!(int, int)); assert(!isSameAttribute!(int, uint)); assert(!isSameAttribute!(int, 1)); assert(!isSameAttribute!(1, int)); struct S {int i;} assert(!isSameAttribute!(S(1), 1)); assert( isSameAttribute!(S(1), S(1))); } private template _attrOfType(alias OfType, Attrs...) { static if(Attrs.length == 0) { alias Tuple!() _attrOfType; } else static if(Attrs.length == 1) { static if(isSameAttribute!(Attrs[0], OfType)) alias Tuple!(Attrs[0]) _attrOfType; else alias Tuple!() _attrOfType; } else { alias _attrOfType!(OfType, Attrs[1..$]) Rest; static if(isSameAttribute!(Attrs[0], OfType)) alias Tuple!(Attrs[0], Rest) _attrOfType; else alias Tuple!(Rest) _attrOfType; } } unittest { struct A1 { int i; } (1, A1, A1(1), A1(2)) struct S1 {} assert(attrOfType!(2, S1).length == 0); assert(attrOfType!(1, S1).length == 1); assert(attrOfType!(1, S1)[0] == 1); assert(attrOfType!(A1, S1).length == 1); assert(is(attrOfType!(A1, S1)[0] == A1)); assert(attrOfType!(A1(1), S1).length == 1); assert(attrOfType!(A1(1), S1)[0] == A1(1)); assert(attrOfType!(A1(2), S1).length == 1); assert(attrOfType!(A1(2), S1)[0] == A1(2)); }
Mar 11 2013
parent reply Jacob Carlborg <doob me.com> writes:
On 2013-03-11 21:41, simendsjo wrote:

 Some update.. Using a custom Tuple(T...) makes things a bit smoother.
 Here's my first working test with two templates: hasAttr to see if an
 attribute exists, and attrOfType to get all attributes matching a type
 (not sure if I should include values..)
You need to use TypeTuple and not Tuple. This is my library functions for UDA's: https://github.com/jacob-carlborg/orange/blob/master/orange/core/Attribute.d -- /Jacob Carlborg
Mar 17 2013
parent "simendsjo" <simendsjo gmail.com> writes:
On Sunday, 17 March 2013 at 14:46:59 UTC, Jacob Carlborg wrote:
 On 2013-03-11 21:41, simendsjo wrote:

 Some update.. Using a custom Tuple(T...) makes things a bit 
 smoother.
 Here's my first working test with two templates: hasAttr to 
 see if an
 attribute exists, and attrOfType to get all attributes 
 matching a type
 (not sure if I should include values..)
You need to use TypeTuple and not Tuple. This is my library functions for UDA's: https://github.com/jacob-carlborg/orange/blob/master/orange/core/Attribute.d
Thanks. I've gotten quite far already: struct A { int i; } ("struct S") struct S { ("int i", 0, 1, S, A(-1)) int i; ("string a", "aoeu", 2, string, A(10)) string a; ("long f(int i)") long f(int i) { return i; } } alias TypeTuple!( TupleWrapper!(S, "struct S") , TupleWrapper!(S.i, "int i", 0, 1, S, A(-1)) , TupleWrapper!(S.a, "string a", "aoeu", 2, string, A(10)) , TupleWrapper!(S.f, "long f(int i)") ) Expected; alias getMembersAndAttributes!S Actual; static assert(isEqual!(TupleWrapper!Expected, TupleWrapper!Actual));
Mar 17 2013