Passing ref through a template chain

Jacob Carlborg doob at me.com
Mon Oct 3 06:25:07 PDT 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
> Steve

Does this work:

void setSeveral(T...)(ref T args)
{
    foreach (i, _; args)
       setTarget(args[i], i);
}

Or you already tried that in setSeveral2.

-- 
/Jacob Carlborg


More information about the Digitalmars-d-learn mailing list