On 27 April 2013 13:29, Diggory <diggsey@googlemail.com> wrote:
I don't see myself ever getting on board with this auto-ref idea. I just
think it's crazy. It makes no sense to me, they are completely unrelated
concepts. It will only lead to confusion.

I'm back at scope-ref. Kenji is right as far as I'm concerned. Not to
mention, he actually did the work.
It makes perfect sense, and I can't see any reason why auto-ref should be
used instead of something that actually makes intuitive sense, and people
will eventually want to use anyway...

I'm against "scope ref" as the one thing "scope" means is that the parameter cannot be returned, and preventing rvalue references being returned breaks the one thing they are useful for.

It would have to return 'scope ref' also. This returns ownership to the calling statement, which is fine, because it is where the temporary originated in the first place.


The primary use of rvalue references in C++ is so that these three cases work:
vector<T> vec;
T t;
vec.push_back(T()) // Move semantics (temporary is destroyed in the process)
vec.push_back(t) // Copy semantics ('t' is unmodified)
vec.push_back(move(t)) // Move semantics ('t' is destroyed in the process)

This allows best efficiency (move is at least as fast as copy, so when the original is no longer needed a move should be performed)

The way it works is that push_back() has two overloads:
push_back(T&& v) {
    // Move 'v' into the vector, afterwards 'v' will have had its guts ripped out so to speak...
}
push_back(const T& v) {
    // Copy 'v' into the vector, 'v' is unmodified
}

- r-values such as 'T()' will default to the first overload.
- l-values such as 't' will default to the second overload.
- 'move(t)' returns an r-value causing the first overload to be called.

As you can see, using "scope ref" will break this third case because 'move()' won't be able to return an r-value, and if only the first two cases are going to be possible, this can be done without any special notion of r-value references anyway.

I'm starting to think there does need to be new syntax if all three of the above cases are to be covered - it would work just making "ref" accept rvalues but then "move" would be the default for lvalues, and that would be confusing - but I don't think using "scope" solves any problems, as the semantics required for rvalues are orthogonal to what "scope" actually means.

As good as it is to avoid adding new keywords, I think this might be a case where it's warranted...

scope ref T func(scope ref T t) { return t; }

I think this solves the problem.