digitalmars.D.learn - Template alias parameters to local variables
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (67/67) Sep 13 2014 Consider the following code:
- Kagamin (1/1) Sep 14 2014 Doesn't this cause infinite recursion?
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (4/5) Sep 14 2014 No, because the inner templates are instantiated with different
- "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm gmx.net> (2/74) Sep 17 2014 Anyone an idea?
Consider the following code: alias Sink = scope void delegate(const(char)[]); private template generateAliases(int __i, __vars...) { import std.conv : to; static if(__i < __vars.length) enum generateAliases = "alias " ~ __vars[__i].stringof ~ " = __vars[" ~ __i.to!string ~ "];\n" ~ generateAliases!(__i+1, __vars); else enum generateAliases = ""; } template render(string __tpl, __vars...) { void render(Sink sink) { static void render2(string __tpl2, __vars2...)(Sink sink2 = sink) { .render!(__tpl2, __vars2)(sink2); } void render3(string __tpl2, __vars2...)(Sink sink2 = sink) { .render!(__tpl2, __vars2)(sink2); } alias __sink = sink; mixin(generateAliases!(0, __vars)); //mixin(generateRenderer(__tpl)); alias x = __vars[0]; alias y = __vars[1]; render2!("...", x, y); // ERROR render3!("...", x, y); // ERROR } } void main() { import std.stdio; int a, b; render!("...", a, b)(s => write(s)); } Inside the `render` function, which takes a string and several variables as template parameters, as well as a delegate as runtime parameter, I want another function to be available, which should again accept a string and several aliases (including some that `render` previously received as aliases). At the same time, the function should implicitly pick up the sink that has been passed to `render`. I'm trying to slightly different implementations, `render2` and `render3`. They both produce compile errors: render2: test.d(16): Error: static function test.main.render!("...", a, b).render2 cannot access frame of function D main test.d(29): Error: static function test.main.render!("...", a, b).render2 cannot access frame of function D main render3: test.d(30): Error: template instance render3!("...", a, b) cannot use local 'a' as parameter to non-global template render3(string __tpl2, __vars2...)(Sink sink2 = sink) I would prefer `render2`, because it is static and thus doesn't need to allocate a context for the sink. Indeed, it used to work before this issue was fixed: https://issues.dlang.org/show_bug.cgi?id=11946 https://github.com/D-Programming-Language/dmd/pull/3884 Now, has this fix gone too far? On first glance, the `render2` error message seems to make sense, but why doesn't the same error occur for `render`? However, why doesn't at least `render3` work? It's strange local templates cannot accept local variables as aliases... Alternatively, does anyone know of another way to achieve what I want?
Sep 13 2014
On Sunday, 14 September 2014 at 09:29:16 UTC, Kagamin wrote:Doesn't this cause infinite recursion?No, because the inner templates are instantiated with different first template parameters. Even if all template parameters were the same, it would only be a runtime recursion.
Sep 14 2014
On Saturday, 13 September 2014 at 11:34:01 UTC, Marc Schütz wrote:Consider the following code: alias Sink = scope void delegate(const(char)[]); private template generateAliases(int __i, __vars...) { import std.conv : to; static if(__i < __vars.length) enum generateAliases = "alias " ~ __vars[__i].stringof ~ " = __vars[" ~ __i.to!string ~ "];\n" ~ generateAliases!(__i+1, __vars); else enum generateAliases = ""; } template render(string __tpl, __vars...) { void render(Sink sink) { static void render2(string __tpl2, __vars2...)(Sink sink2 = sink) { .render!(__tpl2, __vars2)(sink2); } void render3(string __tpl2, __vars2...)(Sink sink2 = sink) { .render!(__tpl2, __vars2)(sink2); } alias __sink = sink; mixin(generateAliases!(0, __vars)); //mixin(generateRenderer(__tpl)); alias x = __vars[0]; alias y = __vars[1]; render2!("...", x, y); // ERROR render3!("...", x, y); // ERROR } } void main() { import std.stdio; int a, b; render!("...", a, b)(s => write(s)); } Inside the `render` function, which takes a string and several variables as template parameters, as well as a delegate as runtime parameter, I want another function to be available, which should again accept a string and several aliases (including some that `render` previously received as aliases). At the same time, the function should implicitly pick up the sink that has been passed to `render`. I'm trying to slightly different implementations, `render2` and `render3`. They both produce compile errors: render2: test.d(16): Error: static function test.main.render!("...", a, b).render2 cannot access frame of function D main test.d(29): Error: static function test.main.render!("...", a, b).render2 cannot access frame of function D main render3: test.d(30): Error: template instance render3!("...", a, b) cannot use local 'a' as parameter to non-global template render3(string __tpl2, __vars2...)(Sink sink2 = sink) I would prefer `render2`, because it is static and thus doesn't need to allocate a context for the sink. Indeed, it used to work before this issue was fixed: https://issues.dlang.org/show_bug.cgi?id=11946 https://github.com/D-Programming-Language/dmd/pull/3884 Now, has this fix gone too far? On first glance, the `render2` error message seems to make sense, but why doesn't the same error occur for `render`? However, why doesn't at least `render3` work? It's strange local templates cannot accept local variables as aliases... Alternatively, does anyone know of another way to achieve what I want?Anyone an idea?
Sep 17 2014