Mixin and function template?

renoX renosky at free.fr
Fri Mar 2 00:32:05 PST 2007


Frits van Bommel a écrit :
> 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 :).

Great!
Thanks a lot!

renoX


More information about the Digitalmars-d-learn mailing list