UDA syntax

Ali Çehreli acehreli at yahoo.com
Wed Jan 16 20:38:14 PST 2013


On 01/16/2013 05:59 PM, Joseph Cassman wrote:
> I was wondering what the syntax is for user defined attributes (i.e. bug
> 9222) implemented in release 2.061. I was still unclear after reading
> the thread forum.dlang.org/thread/k7afq6$2832$1 at digitalmars.com.
>
> Thanks for the help
>
> Joseph

The following is the code that I had used for experimenting with UDAs:

import std.stdio;

/* Here we define a type which we will later use to add attributes
  * to. Although this type can have member variables as well, its name 
will be
  * sufficient in this case.
  */
struct SafeToDoFooWith
{}

/* This type has that attribute. This attribute can be obtained at compile
  * time by the __traits(getAttributes) syntax.
  */
@SafeToDoFooWith
struct Struct
{}

/* This type does not have that attribute.
  */
struct AnotherStruct
{}

/* This template is not directly related. (I expect it to be in Phobos; 
maybe
  * it's already there. (?))
  */
template hasAttribute(T, AttributeInQuestion)
{
     bool does_have()
     {
         /* UDAs can be obtained by __traits(getAttributes). This loop is a
          * linear search.
          */
         foreach (t; __traits(getAttributes, T)) {
             if (typeid(t) is typeid(AttributeInQuestion)) {
                 return true;
             }
         }

         return false;
     }

     enum hasAttribute = does_have();
}

/* This is a function that demonstrates how UDAs can affect code. */
void foo(T)(T parameter)
{
     /* UDA are a fully compile-time feature. */
     static if (hasAttribute!(T, SafeToDoFooWith)) {
         writefln("'%s' can safely be copied. Copying...", T.stringof);
         T theCopy = parameter;
         /* ... the rest of the algorithm ... */

     } else {
         writefln("It is not safe to copy '%s'. Must use a different 
algorithm.",
                  T.stringof);
         /* ... another algorithm ... */
     }
}

void main()
{
     auto y = Struct();
     foo(y);

     auto by = AnotherStruct();
     foo(by);
}

The following program demonstrates how to have multiple attributes as 
well as how to test for the presence of a particular attribute value.

import std.stdio;

/* Whether one of the attributes matches the specified type and value. */
bool hasAttributeValue(T, D)(D value)
{
     foreach (t; __traits(getAttributes, T)) {
         static if (is (typeof(t) == D)) {
             if (t == value) {
                 return true;
             }
         }
     }

     return false;
}

/* The attributes of this type are two fundamental values. */
@(42, "hello")
struct Struct
{}

void foo(T)(T obj)
{
     static if (hasAttributeValue!T(42) &&
                hasAttributeValue!T("hello")) {
         writeln("Has both attribute values");

     } else {
         writeln("Nope...");
     }
}

void main()
{
     Struct a = Struct();
     foo(a);
}

Ali


More information about the Digitalmars-d-learn mailing list