On 12/6/2014 5:30 AM, "Marc Schütz" <schue...@gmx.net>" wrote:
On Friday, 5 December 2014 at 23:58:41 UTC, Walter Bright wrote:
As you point out, 'ref' is designed for this.
I wouldn't call it "designed", but "repurposed"...
Perhaps, but the original reason to even have 'ref' was so it could be a
restricted pointer type that could be passed down a call hierarchy, but not up.
struct Container(T) {
scope ref T opIndex(size_t index);
}
void bar(scope ref int a);
Container c;
bar(c[42]); // ok
scope ref tmp = c[42]; // nope
Both cases should be fine theoretically; the "real" owner lives longer than
`tmp`. Unfortunately the compiler doesn't know about this.
Right, though the compiler can optimize to produce the equivalent.
??? This is a problem on the semantic level, unrelated to optimization:
// contrived example to illustrated the point
Container c;
scope ref x = c[42]; // not
scope ref y = c[44]; // ...
scope ref z = c[13]; // allowed
foo(x, y, z, x+y, y+z, z+x, x+y+z);
// workaround, but error-prone and has different semantics
// (opIndex may have side effects, called multiple times)
foo(c[42], c[44], c[13], c[42]+c[44], c[44]+c[13], c[13]+c[42],
c[42]+c[44]+c[13]);
// another workaround, same semantics, but ugly and unreadable
(scope ref int x, scope ref int y, scope ref int z) {
foo(x, y, z, x+y, y+z, z+x, x+y+z);
}(c[42], c[44], c[13]);
You are correct, and it remains to be seen if these occur enough to be a problem
or not. The workarounds do exist, though. Another workaround:
scope ref tmp = c[42];
becomes:
auto scope ref tmp() { return c[42]; }
Ok, so let's drop bar2() and bar4().
scope ref int foo();
scope ref int bar1(ref int a) {
return a;
}
ref int bar3(ref int a) {
return a;
}
ref int baz_noscope(/*scope*/ ref int a);
foo().bar1().baz_noscope();
foo().bar3().baz_noscope();
And now? In particular, will the return value of `bar3` be treated as if it were
`scope ref`?
Yes.