The first version is generally better. There's no significant difference in compiliation performance (if any, forrmat isn't ctfe), and format() should actually perform better.
The binary "foo" ~ "bar" is often surprisingly expensive because it allocates intermediate results that the garbage collector then has to clean up.
On the dmd version I have, neither version actually compiles as safe, nothrow, pure. I think they fixed this in phobos git, but I'm not sure. Regardless, right now neither actually works, and there's no easy workaround aside from implementing your own function, unless it is just for debugging.
The pure requirement is relaxed in debug statements, and you can wrap non-@safe functions in @system, and throwing functions in try/catch to get those attributes in.
Thus, this would actually compile:
// trusted gets around safe
@trusted pure nothrow string myformat(T...)(in string fmt, in T t) {
import std.string;
// debug gets around the pure requirement
debug try // try gets around nothrow
return format(fmt, t);
catch(Exception e) { }
return null;
}
@safe nothrow pure void main() {
import std.conv;
string s = myformat("test %s", 10);
assert(0, s); // the assert message shows up
}
compile with the -debug switch: dmd test.d -debug
So not a great solution, but until the phobos functions with the proper attributes are released, or if you want to write your own format() or to() functions (not really that hard, you can do int to string in < 10 lines) probably the best you can do.