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