views:

80

answers:

1

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 to rdmd, 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 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?

+1  A: 

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

BCS
Thanks for the answer. The advantage of not specifically testing for functions is that you can use other kinds of callable values, but I agree, this is cleaner. It also seems that the closest we have to examples of idiomatic D at the moment come from the Phobos source :)
shambulator