www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Versionable default parameters

Is it possible to change what parameters a function takes by flipping a
-version switch?  Turns out, the answer is yes: while trying to work out
a nice fix for issue 14892, I discovered the following interesting
little "hack":

import std;

    // Fake function from which to extract parameter tuple.
    void locusFunc(string file = __FILE__, size_t line = __LINE__,
                   string func = __FUNCTION__);

    // Bind parameter declarations to an alias
    static if (is(typeof(locusFunc) Params == __parameters))
        alias Locus = Params;
        static assert(0, "Not a function");
    alias Locus = AliasSeq!();

// Optionally inject default parameters, contingent on whether we're
// compiling with -version=traceFuncCalls.
void realFunc(string someOther, int args, Locus locus) {
    if (locus.length > 0)
        writefln("Locus = %s %s %s", locus);
        writeln("no locus");

void main() {
    realFunc("", 0); // look, ma! Automatic location tracking in callee!

Compile with/without -version=traceFuncCalls to see the effect.
Basically, with this -version, Locus injects the 3 default parameters
into the function call to realFunc.  When *not* compiling with -version,
Locus is the empty tuple, and basically erases itself from realFunc's
parameter list.  So zero runtime cost is incurred: the extra parameters
aren't even passed to realFunc.  Only when we compile with -version,
the extra parameters will be inserted -- automatically.

This would have been a wonderful solution for the -profile=gc situation:
we would have been able to inject these extra parameters into Phobos
functions only when compiled with -profile=gc (I changed dmd to
predefine version=D_ProfileGC in this case, so the above version test
could just be changed to test for this), otherwise no extra parameters
would be passed and no extra cost would be incurred.

Unfortunately, this is only a "would have been": because of the fatal
flaw that the above trick does not work with template functions.  IFTI
gets tripped up by the alias and is unable to match the template
instantiation when the default arguments are not supplied. :-( :-(


I think the conspiracy theorists are out to get us...
Jan 18