digitalmars.D.learn - Traits and UDAs
- Chris Williams (46/46) Jun 06 2013 I decided to write up a little application to test using User
- Adam D. Ruppe (52/52) Jun 06 2013 Here's how I do it:
- Dicebot (4/5) Jun 06 2013 It will work if use "enum" instead of "auto" for storing
I decided to write up a little application to test using User
Defined Attributes and have one question. Here is a working
application that allows me to mark certain members of a function
to be dumped:
import std.stdio;
enum Dump = "Dump";
template Dumper(T) {
void dump() {
foreach (mem; __traits(allMembers, T)) {
auto attributes = __traits(getAttributes, __traits(getMember,
T, mem));
static if ( attributes.length > 0 && __traits(getAttributes,
__traits(getMember, T, mem))[0] == Dump ) {
writeln(mem);
}
}
}
}
class Foo {
Dump int hello;
Dump int world;
int bye;
mixin Dumper!(Foo);
}
int main(string[] args) {
Foo f = new Foo();
f.dump();
return 0;
}
The eighth line bothers me, though. It seems like I should be
able to write:
if (attributes.length > 0 && attributes[0] == Dump)
However, that fails to compile with the message:
test.d(7): Error: variable _attributes_field_0 cannot be read at
compile time
test.d(8): Error: expression !!(_attributes_field_0 == "Dump") is
not constant or does not evaluate to a bool
test.d(7): Error: variable _attributes_field_0 cannot be read at
compile time
test.d(8): Error: expression !!(_attributes_field_0 == "Dump") is
not constant or does not evaluate to a bool
Any thoughts?
Jun 06 2013
Here's how I do it:
enum Dump; // just a type, no value here
template Dumper(T) {
void dump() {
foreach (mem; __traits(allMembers, T)) {
// loop over the attrs instead of try to store them in a
var
foreach(attr; __traits(getAttributes, __traits(getMember,
T, mem)))
// identify them by type rather than value
static if ( is(attr == Dump)) {
writeln(mem);
}
}
}
}
Or some helper functions might be good. Here's the ones I did:
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;
}
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;
}
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;
}
hasAnnotation!(something, Dump) tells you if it is just there
hasValueAnnotation tells you if the annoation has a value (enum
Dump; won't, but struct Dump { int option; } would).
getAnnotation fetches the value.
The "something" argument there is a symbol, e.g.
__traits(getMember, T, mem). The second argument is the type
you're interested in.
Jun 06 2013
On Thursday, 6 June 2013 at 17:50:08 UTC, Chris Williams wrote:...It will work if use "enum" instead of "auto" for storing attribute tuple. If compile-time value is needed you almost always want to store it in enum.
Jun 06 2013









"Adam D. Ruppe" <destructionator gmail.com> 