A little example ...
import std.stdio; import std.traits; import std.typetuple; import std.metastrings;
alias ParameterStorageClassTuple PSCT; alias ParameterStorageClass PSC; alias ParameterTypeTuple PTT; string ToStorageName(alias T)() { static if(T == PSC.REF) return "ref"; else static if (T == PSC.OUT) return "out"; else static if (T == PSC.LAZY) return "lazy"; else static if (T == PSC.SCOPE) return "scope"; else static if (T == PSC.NONE) return "in"; else static assert(false, "other"); } string PrintStorageTuple(int index, alias F, STs...)() { alias PTT!F Ts; string ret = ""; static if (STs.length > 0) { ret ~= ToStorageName!(STs[0])() ~ " " ~ Ts[0].stringof; ret ~= " arg" ~ toStringNow!(index); } static if (STs.length > 1) { void func(Ts[1..$] a) { } const a = index + 1; ret ~= ", " ~ PrintStorageTuple!(a, func, STs[1..$])(); } return ret; } string PrintStorage(alias F)(string name) { alias PSCT!F STs; string ret = "auto " ~ name ~ "(" ~ PrintStorageTuple!(0, F, STs)() ~ ")"; return ret; } // **** tests int Multiply(int a, int b, out int c) { return c = a * b; } mixin(PrintStorage!Multiply("DebugMultiply") ~ q{ { writeln("DEBUG: ", arg0, " ", arg1, " ", arg2); return Multiply(arg0, arg1, arg2); } }); void main() { int a= 10, b = -3, c; writeln(Multiply(a, b, c)); writeln(c); a = 3; b = -4; writeln(DebugMultiply(a, b, c)); writeln(c); }