www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - UDA usage

reply Matt Soucy <msoucy csh.rit.edu> writes:
So, I was away from active D development for a while, and I'm having
trouble finding info about how to use UDAs. I can see the basics, like
how to apply a UDA to a symbol, but now how to do specific things, like:
* Check to see if a specific attribute exists
* Check to see if an attribute of a specific type exists, something like:=

 Foo('a') int x;
enum hasAnyFoo =3D __traits(hasAttributeOfType, Foo, x);
* Create a function that can only be called if the first argument has a
UDA of a specific type

Are any of these doable?
Thank you,
-Matt Soucy
Oct 04 2013
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Saturday, 5 October 2013 at 02:51:21 UTC, Matt Soucy wrote:
 * Check to see if a specific attribute exists
 * Check to see if an attribute of a specific type exists, 
 something like:
The helper functions from my web.d might help: // checks to see if it has one of a type // static if(hasAnnotation!(func, Foo)) { has Foo } // use if Foo is a simple enum. 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; } /// checks to see if it has an annotation with a value e.g. Something(10) template hasValueAnnotation(alias f, Attr) { bool helper() { foreach(attr; __traits(getAttributes, f)) static if(is(typeof(attr) == Attr)) return true; return false; } enum bool hasValueAnnotation = helper; } /// gets the thing you checked for above. so getAnnotation!(Func, Something) returns Something(10) (if Something is as struct) template getAnnotation(alias f, Attr) if(hasValueAnnotation!(f, Attr)) { auto helper() { foreach(attr; __traits(getAttributes, f)) static if(is(typeof(attr) == Attr)) return attr; assert(0); } enum getAnnotation = helper; }
 * Create a function that can only be called if the first 
 argument has a
 UDA of a specific type
Since the UDA is only available at compile time, you can't do that without some kind of template.
Oct 04 2013
parent reply Matt Soucy <msoucy csh.rit.edu> writes:
On 10/04/2013 11:04 PM, Adam D. Ruppe wrote:
 On Saturday, 5 October 2013 at 02:51:21 UTC, Matt Soucy wrote:
 * Check to see if a specific attribute exists
 * Check to see if an attribute of a specific type exists, something li=
ke:
=20
 The helper functions from my web.d might help:
=20
 // checks to see if it has one of a type
 // static if(hasAnnotation!(func, Foo)) { has  Foo }
 // use if Foo is a simple enum.
 template hasAnnotation(alias f, Attr) {
     bool helper() {
         foreach(attr; __traits(getAttributes, f))
             static if(is(attr =3D=3D Attr) || is(typeof(attr) =3D=3D At=
tr))
                 return true;
         return false;
=20
     }
     enum bool hasAnnotation =3D helper;
 }
=20
 /// checks to see if it has an annotation with a value e.g.  Something(=
10)
 template hasValueAnnotation(alias f, Attr) {
     bool helper() {
         foreach(attr; __traits(getAttributes, f))
             static if(is(typeof(attr) =3D=3D Attr))
                 return true;
         return false;
=20
     }
     enum bool hasValueAnnotation =3D helper;
 }
=20
 /// gets the thing you checked for above. so getAnnotation!(Func,
 Something) returns Something(10) (if Something is as struct)
 template getAnnotation(alias f, Attr) if(hasValueAnnotation!(f, Attr)) =
{
     auto helper() {
         foreach(attr; __traits(getAttributes, f))
             static if(is(typeof(attr) =3D=3D Attr))
                 return attr;
         assert(0);
     }
=20
     enum getAnnotation =3D helper;
 }
=20
=20
Nice, thank you. These are really helpful!
 * Create a function that can only be called if the first argument has =
a
 UDA of a specific type
=20 Since the UDA is only available at compile time, you can't do that without some kind of template.
Using the above tools I got what I wanted, so I'm satisfied for now. Thank you, though! -Matt Soucy
Oct 04 2013
parent reply Matt Soucy <msoucy csh.rit.edu> writes:
On 10/04/2013 11:50 PM, Matt Soucy wrote:
 On 10/04/2013 11:04 PM, Adam D. Ruppe wrote:
 On Saturday, 5 October 2013 at 02:51:21 UTC, Matt Soucy wrote:
 * Check to see if a specific attribute exists
 * Check to see if an attribute of a specific type exists, something l=
ike:
 The helper functions from my web.d might help:

 // checks to see if it has one of a type
 // static if(hasAnnotation!(func, Foo)) { has  Foo }
 // use if Foo is a simple enum.
 template hasAnnotation(alias f, Attr) {
     bool helper() {
         foreach(attr; __traits(getAttributes, f))
             static if(is(attr =3D=3D Attr) || is(typeof(attr) =3D=3D A=
ttr))
                 return true;
         return false;

     }
     enum bool hasAnnotation =3D helper;
 }

 /// checks to see if it has an annotation with a value e.g.  Something=
(10)
 template hasValueAnnotation(alias f, Attr) {
     bool helper() {
         foreach(attr; __traits(getAttributes, f))
             static if(is(typeof(attr) =3D=3D Attr))
                 return true;
         return false;

     }
     enum bool hasValueAnnotation =3D helper;
 }

 /// gets the thing you checked for above. so getAnnotation!(Func,
 Something) returns Something(10) (if Something is as struct)
 template getAnnotation(alias f, Attr) if(hasValueAnnotation!(f, Attr))=
{
     auto helper() {
         foreach(attr; __traits(getAttributes, f))
             static if(is(typeof(attr) =3D=3D Attr))
                 return attr;
         assert(0);
     }

     enum getAnnotation =3D helper;
 }
=20 Nice, thank you. These are really helpful! =20
 * Create a function that can only be called if the first argument has=
a
 UDA of a specific type
Since the UDA is only available at compile time, you can't do that without some kind of template.
=20 Using the above tools I got what I wanted, so I'm satisfied for now. Thank you, though! -Matt Soucy =20 =20
Update on this - unfortunately, I discovered that this doesn't seem to work for any members, due to requiring a specific "this". I can't quite figure out why though... --=20 Matt Soucy http://msoucy.me/
Oct 08 2013
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Tuesday, 8 October 2013 at 20:59:04 UTC, Matt Soucy wrote:
 Update on this - unfortunately, I discovered that this doesn't 
 seem to work for any members, due to requiring a specific 
 "this". I can't quite figure out why though...
Try adding static to the helper functions in the templates. I just did that and this worked: struct Whoa { int a; } class Foo { lol void argh() {} Whoa(12) int keanu; } void main() { pragma(msg, hasAnnotation!(Foo.argh, lol)); pragma(msg, getAnnotation!(Foo.keanu, Whoa)); } ~$ dmd test34 true Whoa(12) The change to get it to compile was just this: template hasValueAnnotation(alias f, Attr) { static bool helper() { // added static and so on for all three of the helper functions, just make them all static.
Oct 08 2013