specializing template with string variable in CTFE

via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Oct 26 05:46:06 PDT 2014


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.


More information about the Digitalmars-d-learn mailing list