On Sunday, 26 October 2014 at 10:48:46 UTC, ketmar via
Digitalmars-d-learn wrote:
Hello.
the following code is not working:
template prstr(string s) {
enum prstr = "write("~s.stringof~");\n";
}
string buildWriter() (string fmt) {
return prstr!(fmt[0..$-1]);
}
string writer(string fmt) () {
enum s = buildWriter(fmt);
return s;
}
void main () {
import std.stdio;
writeln(writer!"str"());
}
z40.d(6): Error: variable fmt cannot be read at compile time
z40.d(10): Error: template instance z40.buildWriter!() error
instantiating
z40.d(16): instantiated from here: writer!"str"
but why? fmt is known in CTFE and compiler can use it as string
literal
for instantiating `prstr`.
please, don't mind the idiocity of the code: this is just a
sample to
show what confuses me. i know about possibility of moving `fmt`
to
template argument, but i need it as function argument, 'cause
`buildWriter()` actually does string processing and i want to
instantiate `prstr` with the part of the string. and this
processing
cannot be done in 'foreach'.
and writing everything in functional style sux: it leads to
explosive
growing of the number of arguments passed to templates.
Ok, I see two possibilities. The first is to make `prstr` into a
normal function. You cannot use `stringof` then, but need to
escape the string yourself. Luckily, std.format provides
functionality for this already, albeit a bit hidden:
private auto escapeStringLiteral(string s) {
import std.format : formatElement, FormatSpec;
import std.range : appender;
auto app = appender!string;
FormatSpec!char f;
formatElement(app, s, f);
return app.data;
}
The second possibility doesn't exist right now. The core problem
is that the compiler needs to be able to generate runtime code
for `buildWriter()`, because it's just a function after all. But
there have been calls for compile-time only functions, or
something along the lines of `static if(__ctfe)` (which doesn't
work currently and was recently made an error). In this case,
there might be a chance to allow what you want.