Mixin and function template?

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Thu Mar 1 18:03:08 PST 2007


renoX wrote:
> Frits van Bommel a écrit :
>> renoX wrote:
>>> char[] sputf(A...)()
>>> {
>>>      return "std.string.format("~Fmt!(A) ~ ");";
>>> }
>>>
>>> And still call it like you do above?
>>> It doesn't work when I try to do this, I don't understand why..
>>
>> For one thing, the ';' shouldn't be there.
> 
> Weird, the template that I had already for the 'writef equivalent' was:
> template putf(A...)
> {
>     const char[] putf = "writef(" ~ Fmt!(A) ~ ");";
> }
> Here the ';' didn't create a problem, it's string that in the sputf 
> template function it creates a problem..

There are three kinds of mixins[1]: mixin declarations, mixin statements 
and mixin expressions. Your putf string is used as a mixin statement, 
while the sputf string is used as a mixin expression.
See http://www.digitalmars.com/d/changelog.html#new1_005 for the spec 
links, but essentially mixin statements generate statements (including 
any terminating ';'s) while mixin expressions just generate 
(sub)expressions, which don't contain ';'s.


[1] excluding template mixins, which are a different beast altogether.

>> Then you get this:
>> ---
>> import std.stdio;
>> import std.string;
>>
>> /** dummy Fmt!() for testing. This example assumes it accepts a
>>  *  tuple and returns format() parameters in string form.
>>  */
>> template Fmt(A...) {
>>     const char[] Fmt = `"%d", x`;
>> }
>>
>> char[] sputf(A...)()
>> {
>>      return "std.string.format(" ~ Fmt!(A) ~ ")";
>> }
>>
>> void main(char[][] args) {
>>     char[] ret;
>>     int x = 2007;
>>         ret = mixin(sputf!("%d{x}"));
>>         writefln("%s", ret);
>> }
>> ---
>> which seems to work.
> 
> Yes, but what is a bit strange is that if x is an int variable
> res = mixin(sputf!("%d",x)); fails (it works if x is a const int)
> but mixin(putf!("%d",x)); works (putf being the template given above).

The behaviors differ? That's a bit weird...
They both use template parameters, so they should have the exact same 
restrictions AFAIK.

[a bit of research later]
I think this is a restriction of compile-time function evaluation.
 From http://www.digitalmars.com/d/function.html#interpretation :
---
expressions in the function may not:
[snip]
     * reference any global state or variables
     * reference any local static variables
[snip]
---
Those /could/ be interpreted to disallow alias template parameter usage...

Luckily the fix is easy, just transform it to be similar to your putf 
template to avoid CTFE:
---
template sputf(A...)
{
      const sputf = "std.string.format(" ~ Fmt!(A) ~ ")";
}
---
works perfectly fine, even with non-constant integer variables as 
parameters.

And the call syntax didn't even change :).


More information about the Digitalmars-d-learn mailing list