C++ Logo

std-proposals

Advanced search

Re: Guaranteed copy elision for named return values

From: Anton Zhilin <antonyzhilin_at_[hidden]>
Date: Sat, 4 Jan 2020 01:31:27 +0300
(I've accidentally replied personally the first time, sorry for that.)


> 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.)


I've read the Slack thread, and it looks like I'll have to pull this part
off. I wrote it as a [Note] to underline that this follows on its own from
the current [class.copy.elision], in my vision. If this proposal is
adopted, another proposal for guaranteed copy elision for lifetime-extended
references can follow, along with a defect report on the existing wording.
If anyone cares, that is.
For now, I've edited that note not to be innovative.

    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?


It is. And if you remove if(rand()), then one is still not a named return
value.
By the way, NRVO has "return value", but it's actually "return object" in
the standard, so it should probably be "named return object".
I've now replaced "named return value" with "named return object", and in
the name of the proposal, too. What do you think about that?

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.)


I understand the distinction. I included a reference to P1144, because it
also lies in the group of proposals that "reduce moving". In that general
group, there is a subgroup of relocation-related proposals and a subgroup
of proposals that eliminate the need for a move altogether.

пт, 3 янв. 2020 г. в 23:35, Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>:

> On Fri, Jan 3, 2020 at 2:17 PM Anton Zhilin via Std-Proposals <
> std-proposals_at_[hidden]> 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.
>>
>> The proposal link:
>> https://gist.github.com/Anton3/594141354ff9625db0b85775799312c7
>>
>
> 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.)
>
> // https://godbolt.org/z/JrW848
> 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
>

Received on 2020-01-03 16:34:10