Created
January 14, 2015 03:53
-
-
Save esnya/f9f94b3ec22399cc0208 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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