UDA status

simendsjo simendsjo at gmail.com
Mon Mar 11 13:41:06 PDT 2013


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


More information about the Digitalmars-d-learn mailing list