Reputation: 5706
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:
--main
passed to rdmd
, because--main
for modules that define their own, when automatically running unit tests for every file in a directory hierarchy -- the exit code from rdmd
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?
Upvotes: 2
Views: 206
Reputation: 78683
You could try comparing it to a function type:
enum isMainArgTypes = is(typeof(&main) == int function()) ||
is(typeof(&main) == void function()) ||
is(typeof(&main) == int function(string[])) ||
is(typeof(&main) == void function(string[]));
No shorter but it looks cleaner as it needs no static if
Upvotes: 1