On Tuesday, 23 June 2015 at 09:57:26 UTC, Marc Schütz wrote:
On Monday, 22 June 2015 at 19:05:28 UTC, kinke wrote:
[...]
To clarify: What I meant by my comment was that const-ness
should not be a precondition for allowing rvalue refs. Mutable
rvalue refs are fine.
I know and see it the same way.
As I have already pointed out in another thread, I'd go one
step further and propose an extremely convenient `in T` for
this very common use case:
* The argument is passed by value (`const T`) if the compiler
assumes moving/copying is more efficient than passing a
reference (with its indirection on the callee side) for the
particular target environment (hardware, ABI), e.g., for
plain-old-datatypes T fitting into 1-2 registers, and Object
references obviously.
* Otherwise, the argument is passed by-ref (`in ref T`). As
`in T` doesn't mention any ref at all, it's clear that the
hidden reference cannot escape.
Theoretically, `immutable ref` by itself would already allow
these semantics (without the `scope` that `in` implies).
Because (disregarding identity/addresses) for an immutable
object there is no observable difference between pass-by-value
and pass-by-reference. The same is not always true for `const
ref`, whenever aliasing is possible:
void foo(const ref int a, ref int b) {
int x = a;
b++;
assert(x == a); // can fail if both refer to the same
variable
// similar with global variables
}
To guarantee this from the caller's POV, the callee must be
pure and the parameters must be known not to alias each other.
This is obviously true. Rvalues aren't affected as they cannot
alias another parameter by definition. Lvalues are if passed by
ref and the same instance is accessible by mutable ref from
another parameter or global. But as shown by your example, that
danger is always there. The proposed `in` semantics make it less
obvious, that's true, but I still think it'd be worth it, as
these aliasing bugs are a pain to track down, but in my
experience extremely rare.