Compile time features

Shammah Chancellor via Digitalmars-d digitalmars-d at puremagic.com
Wed Oct 28 19:43:57 PDT 2015


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");
}
```


More information about the Digitalmars-d mailing list