import std.traits : PTT=ParameterTypeTuple;
import std.stdio : stderr;
import std.datetime : Clock;
template StringOf(TS...)
{
static if(TS.length == 0)
{
enum StringOf = "";
}
else
{
enum StringOf = (TS[0]).stringof ~ ( (TS.length == 1)? "" : ("," ~ StringOf!(TS[1..$])) );
}
}
template ArgStringOf(TS...)
{
static if(TS.length == 0)
{
enum ArgStringOf = "";
}
else
{
enum ArgStringOf = TS[0] ~ ( (TS.length == 1)? "" : ("," ~ ArgStringOf!(TS[1..$])) );
}
}
template info(PS...)
{
//pragma(msg, info);
const char[] info = `static if(!__traits(compiles, __FUNCTION__ == ""))` ~
`{ immutable string __FUNCTION__ = __traits(identifier, __traits(parent, {})) ~` ~
`"(" ~ StringOf!(PTT!(__traits(parent, {}))) ~ ")";` ~
`} stderr.writeln(Clock.currTime(), " [INFO] ", __FILE__, '(', __LINE__, "): ",` ~
`__FUNCTION__, ": ",` ~ ArgStringOf!(PS) ~ `);` ;
}
mixin template set_func_name(string fn)
{
immutable string __FUNCTION__ = fn;
}
auto foo(T)(in T val)
if(is(T==int) || is(T==string))
{
mixin set_func_name!("foo(" ~ T.stringof ~ ")"); //workaround for fwd ref issue
mixin (info!(`"started"`));
mixin (info!(`"stopped"`));
static if (is(T==int))
return 1.0123;
else static if(is(T==string))
return true;
else
static assert(false, "need int or string");
}
void main(string[] args)
{
mixin (info!(`"started"`));
mixin (info!(`"foo(1) returned: "`, `foo(1)`));
mixin (info!(`"foo(\"bar\") returned: "`, `foo("bar")`));
mixin (info!(`"stopped"`));
}