Skip to content

Instantly share code, notes, and snippets.

@esnya
Created January 14, 2015 03:53
Show Gist options
  • Save esnya/f9f94b3ec22399cc0208 to your computer and use it in GitHub Desktop.
Save esnya/f9f94b3ec22399cc0208 to your computer and use it in GitHub Desktop.
import std.typetuple;
version (unittest) {
enum Attr1;
enum Attr2;
struct Foo {
@Attr1 int x;
@Attr1 int y;
@Attr1 @Attr2 int z;
@Attr2 int u;
int v;
}
}
template Equal(T...) if (T.length == 1) {
enum Equal = true;
}
template Equal(T...) if (T.length >= 2) {
enum Equal = is(T[0] == T[1]) && Equal!(T[1..$]);
}
unittest {
static assert(Equal!(string, string));
static assert(!Equal!(int, string));
}
template Bind(alias T, U) {
template Bind(V...) {
alias Bind = T!(U, V);
}
}
template Bind(alias T, alias U) {
template Bind(V...) {
alias Bind = T!(U, V);
}
}
unittest {
alias isString = Bind!(Equal, string);
static assert(isString!string);
static assert(!isString!double);
struct Foo {}
struct Bar {}
alias isFoo = Bind!(Equal, Foo);
static assert(isFoo!Foo);
static assert(!isFoo!Bar);
}
template valueOf(alias T, alias Member) {
ref valueOf(U...)(U value) {
static if (U.length == 0) {
return __traits(getMember, T, Member);
} else if (U.length == 1) {
return __traits(getMember, T, Member) = value;
} else {
static assert(0);
}
}
}
unittest {
auto foo = Foo(1, 2, 3, 4, 5);
assert(valueOf!(foo, "x") == 1);
assert(valueOf!(foo, "y") == 2);
assert(valueOf!(foo, "z") == 3);
assert(valueOf!(foo, "u") == 4);
assert(valueOf!(foo, "v") == 5);
}
template getAttributedMembers(alias Attr, T) {
template hasAttribute(alias Member) {
alias hasAttribute = anySatisfy!(Bind!(Equal, Attr), __traits(getAttributes, __traits(getMember, T, Member)));
}
alias getAttributedMembers = Filter!(hasAttribute, __traits(allMembers, T));
}
template getAttributedMembers(alias Attr, alias T) {
alias getAttributedMembers = staticMap!(Bind!(valueOf, T), getAttributedMembers!(Attr, Foo));
}
unittest {
import std.range;
static assert(equal([getAttributedMembers!(Attr1, Foo)], ["x", "y", "z"]));
static assert(equal([getAttributedMembers!(Attr2, Foo)], ["z", "u"]));
auto foo = Foo(1, 2, 3, 4, 5);
assert(equal([getAttributedMembers!(Attr1, foo)], [1, 2, 3]));
assert(equal([getAttributedMembers!(Attr2, foo)], [3, 4]));
enum sfoo = Foo(6, 7, 8, 9, 0);
static assert(equal([getAttributedMembers!(Attr1, sfoo)], [6, 7, 8]));
static assert(equal([getAttributedMembers!(Attr2, sfoo)], [8, 9]));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment