digitalmars.D.learn - Passing ref through a template chain
- Steve Teale (41/41) Oct 03 2011 To bind variables, the MySQL api wants their addresses - in my tiny exam...
- Jacob Carlborg (10/51) Oct 03 2011 Does this work:
- Steve Teale (3/3) Oct 03 2011 Works like a charm, and it's so obvious a thing to try that I'm kicking ...
To bind variables, the MySQL api wants their addresses - in my tiny example below, these are represented by the void*[]. If I just use something like setTarget in the example, it works fine, but then when I try to set a bunch of them in one go I'm hosed because I can't get the right addresses through the chain. import std.stdio; void*[2] vpa; void setTarget(T)(ref T t, int i) { vpa[i] = &t; } void setSeveral(T...)(ref T args) { foreach (int i, arg; args) setTarget(&arg, i); } //ref.d|19|Error: variable i cannot be read at compile time| //ref.d|19|Error: variable i cannot be read at compile time| //ref.d|19|Error: Integer constant expression expected instead of cast(uint)i| /* void setSeveral2(T...)(ref T args) { for (int i = 0; i < args.length; i++) setTarget(args[i], i); } */ void main() { bool a; int b; setSeveral(a, b); writefln("orig %x %x, set %x %x", &a, &b, vpa[0], vpa[1]); // addresses differ } The problem arises I believe in 'foreach (int i, arg; args)' which makes a copy for 'arg'. Usually in a foreach I can get round that by making it 'ref arg'. But in the template function that does not work. I can't use the setSeveral2() form, because that provokes the errors shown in the comments. How can I force the real addresses through the chain? Thanks Steve
Oct 03 2011
On 2011-10-03 15:08, Steve Teale wrote:To bind variables, the MySQL api wants their addresses - in my tiny example below, these are represented by the void*[]. If I just use something like setTarget in the example, it works fine, but then when I try to set a bunch of them in one go I'm hosed because I can't get the right addresses through the chain. import std.stdio; void*[2] vpa; void setTarget(T)(ref T t, int i) { vpa[i] =&t; } void setSeveral(T...)(ref T args) { foreach (int i, arg; args) setTarget(&arg, i); } //ref.d|19|Error: variable i cannot be read at compile time| //ref.d|19|Error: variable i cannot be read at compile time| //ref.d|19|Error: Integer constant expression expected instead of cast(uint)i| /* void setSeveral2(T...)(ref T args) { for (int i = 0; i< args.length; i++) setTarget(args[i], i); } */ void main() { bool a; int b; setSeveral(a, b); writefln("orig %x %x, set %x %x",&a,&b, vpa[0], vpa[1]); // addresses differ } The problem arises I believe in 'foreach (int i, arg; args)' which makes a copy for 'arg'. Usually in a foreach I can get round that by making it 'ref arg'. But in the template function that does not work. I can't use the setSeveral2() form, because that provokes the errors shown in the comments. How can I force the real addresses through the chain? Thanks SteveDoes this work: void setSeveral(T...)(ref T args) { foreach (i, _; args) setTarget(args[i], i); } Or you already tried that in setSeveral2. -- /Jacob Carlborg
Oct 03 2011
Works like a charm, and it's so obvious a thing to try that I'm kicking myself. Thanks Steve
Oct 03 2011