On Fri, Jan 3, 2020 at 2:17 PM Anton Zhilin via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
Hi! I've prepared a proposal (draft), which aims to provide guaranteed copy elision for common cases of local variables being returned from a function.

This proposal seems more realistic than your similarly motivated "alias-expressions" proposal.

 [ Note: Either the variable is of a non-reference type or it is a reference participating in lifetime extension. — end note ]

This is actually interesting and innovative as far as I know. No current compiler performs copy-elision on local variables of lifetime-extended reference type. As far as I can tell, the paper standard does not permit copy-elision in such situations. (But those two statements are not particularly correlated in real life. David Stone and I have been mostly-independently working on harmonizing practice with specification in these areas. See P0527, P1155, P1825 — P1825 subsumes the other two, and has been adopted for C++2a. P1825 doesn't talk about the lifetime-extension case.)

Widget foo() noexcept;
Widget bar() {
    auto&& w = foo();  // lifetime-extended temporary
    return w;  // no compiler implements copy-elision here
}

If you want to permit copy-elision on lifetime-extended variables, I think you'll have to do some surgery on the existing wording. Weak consensus in the #future-standard channel is that when http://eel.is/c++draft/class.copy.elision#1.1 talks about "the name of a non-volatile automatic object," you'd have to do some real mental gymnastics to interpret that to include non-volatile automatic variables of reference type which happen to refer to a lifetime-extended object. (Especially if you mean to exclude variables of reference type which happen to refer to automatic objects that aren't lifetime-extended.)

// https://godbolt.org/z/JrW848
Widget foo() noexcept;
Widget bar() {
    auto temp = foo();
    auto&& w = temp;  // reference to automatic object of the correct type, but not as a result of lifetime extension
    return w;  // copy-elision here would be insane
}

I'm vaguely skeptical of your use of "potential scope." No particular problem I can see, but I would bet money that there are problems I don't see yet.

    Widget baz() {
        Widget one;
        if (rand()) return one;
        Widget two;
        return two;
    }

IIUC, your proposal mandates that `return two;` must use copy-elision (so `two` must be constructed straight into the return slot), but `return one;` may-or-may-not use copy-elision (which actually means that it cannot possibly use copy-elision, because it must leave the return slot available for `two`). Is that an accurate reading of your proposal's intent?

P1144 "relocation" is 100% unrelated to copy-elision. Copy-elision is a core-language optimization that is done on a single object; trivial relocation is a library-level optimization that is [normally] done on a contiguous range of objects. If you don't have a contiguous range of objects (like a vector reallocation), then performing trivial relocation as an optimization probably doesn't buy you anything that you couldn't get from a good optimizer and the "as-if rule."  Returning a std::unique_ptr<int> "by move" is totally fine; the optimizer will get it.
(The other benefit of P1144 is that sometimes programmers need to use trivial relocation for actual API reasons, such as because some C API requires it. Having the `std::is_trivially_relocatable` trait allows those programmers to static_assert that what they're doing is actually safe.)

my $.02,
–Arthur