I'm writing a module with mixin templates to supply a main
function for unit-testing purposes. Usage is as follows:
/* For modules without their own main, e.g. libraries.
* main is conditionally supplied using version(unittest).
*/
mixin Main;
/* For executable modules defining function "realMain".
* Generated main has the same signature and return type
* as realMain, and transfers control to it. Additionally,
* main exits without calling realMain for version (unittest).
*/
mixin Main!realMain;
The idea is that every module of mine mixes in main
appropriately, so that:
- Libraries don't need
--main
passed tordmd
, because - There seems no good way to decide not to pass
--main
for modules that define their own, when automatically running unit tests for every file in a directory hierarchy -- the exit code fromrdmd
is the same as for a failed compile.
I'm using std.traits
to determine realMain
's validity as a main
function, and ensure that my generated main
has the same signature. Everything seems to be working, but I think it could be cleaner. Currently, my template for checking valid main
arguments looks like this:
template isMainArgTypes(alias main)
{
static if (is(ParameterTypeTuple!main == TypeTuple!()))
enum isMainArgTypes = true;
else static if (ParameterTypeTuple!main.length == 1
&& is(ParameterTypeTuple!main[0] T : const T[]))
{
enum isMainArgTypes = is(T : const char[]);
}
else
enum isMainArgTypes = false;
}
I feel sure there must be some way to condense the middle condition into a single is
expression, without explicitly testing the tuple length and separately checking for a string type, but so far my nascent metaprogramming-fu has fallen short.
Any ideas, D wizards?