Design patterns

To fully take advantage of compile time functionality, it may not be possible to use design patterns that are well known. Normally they take advantage of well definated virtual interfaces to classes to enable swapping between implementations. This is a hinderence when working with compile time and meta-programming. For these situations you must know the exact implementation that you are deal with at all points. A great example of a common design pattern that can be adapted to compile time easily is the visitor pattern. The core difference is in the element instead of specifying the visitor abstraction interface, you use an abstract class as part of the meta programming arguments. An Example in the D programming language:

1 class ConcreteElement : Element {
2 	override void accept(T : Visitor)(T \
3 visitor) {
4 		visitor.visit(this);
5 	}
6 }

At this point it would be simple on Visitor to implement a specific implementation for the Element implementation. Alternatively a similar method to the one above could be used to handle it abstractly. Such as:

1 class ConcreteVisitor : Visitor {
2 	void visit(T : Element)(T obj) {
3 		pragma(msg, T.stringof);
4 	}
5 }

Of note is the runtime if statement support for determining if a class instance inherits from a specific interfaces/class.

1 if (Type to = cast(Type)from) {
2 	...
3 }

This might be useful at compile time if the possible types were limited. However if the purpose is to generate code for runtime usage then checking type using a static if is the right tool.

Helper generators

This design pattern is a general use case one. The term generator is a rather awful designation, but it pushes the thought of what a generator does. It creates something to be used. Under this design pattern there is two types of functions. A helper function is a single purpose function that is designed to execute only at compile time. It mostly requires some form of compile time arguments via e.g. metaprogramming. It uses type information to derive new information and return it. Attributes and returning a specific piece of information from it are a great example. A generator function produces a function to be executed at runtime, but uses compile time information. This calls helper functions to do so.