Currently D has some very very powerful compile time features,
but they can get unwieldily quickly when doing compile time
reflection with mildly complicated logic. It's pretty
disappointing. I'd like to start a discussion around some of the
problems I've ran into using these features. If there aren't
bugzilla reports, I can open them but I'm not entirely sure how
to file these appropriately.
1) There seems to be many cases where __traits(allMembers, ...)
over a package produces symbol strings which cannot be converted
to a symbol using __traits(getMember). Also __traits is not
useable in reasonable contexts( alias foo = __traits(..)). E.g.
This will fail due to weird symbols being returned from
allMembers.
```
import std.stdio;
enum hack(A...) = A;
int main() {
foreach(member; __traits(allMembers, std.stdio)) {
pragma(msg, member);
alias sym = hack!(__traits(getMember, std.stdio, member))[0];
}
return 0;
}
```
2) There are oddities around getting the types of functions which
are properties:
e.g. (Note the __compiles, and addressing the member):
```
//Gets the member type, even for properties.
private template MemberType(C, string memberName)
{
alias member = TypeTuple!(__traits (getMember, C,
memberName))[0];
static if (__traits (compiles, typeof(&member)))
{
static if (isSomeFunction!(typeof(&member)))
{
alias MemberType = typeof(&member);
}
else
{
alias MemberType = typeof(member);
}
} else {
alias MemberType = typeof(member);
}
}
```
3) Additionally, any kind of iteration becomes very unwieldy.
This kind of code becomes necessary in common cases. (E.g. pass
in a list of packages and reduce to a AliasSeq of type symbols)
```
import std.stdio : writeln;
import std.typetuple;
// This won't work:
/+
private template stuff(Args...) {
/+ static +/ foreach(Arg; Args) {
...
}
}
+/
// Must do this instead:
private template expand(Args...)
{
static if (Args.length > 0)
{
static if (Args.length > 1)
{
enum stuff = AliasSeq!(repeat!(Args[0], Args.length),
stuff!(Args[1..$]));
}
else static if (Args.length == 1)
{
enum stuff = AliasSeq!(repeat!(Args[0], Args.length));
}
}
}
private template repeat(alias T, int times) {
static if ( times > 1 ) {
enum repeat = AliasSeq!(T, repeat!(T, times-1));
} else static if (times == 1) {
enum repeat = AliasSeq!(T);
}
}
enum things = expand!("A","B","C");
void main() {
pragma(msg, things);
writeln("Hello World");
}
```