C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Return Value Optimisation whenever you need it (guaranteed elision)

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Sat, 12 Aug 2023 12:32:56 -0400
On Sat, Aug 12, 2023 at 12:14 PM Marcin Jaczewski via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> sob., 12 sie 2023 o 17:43 Thiago Macieira via Std-Proposals
> <std-proposals_at_[hidden]> napisaƂ(a):
> >
> > On Saturday, 12 August 2023 08:33:27 PDT Thiago Macieira via Std-Proposals
> > wrote:
> > > So I'll help. Of what it provided, this is the only one that is a currently
> > > accepted and acceptable syntax:
> > >
> > > int nrvo monkey;
> > >
> > > With nrvo being a new keyword, possibly context-sensitive like final and
> > > override.
> >
> > You know what would help here? Not having a new keyword. So if we could reuse
> > an existing keyword in a way that it can't today be used, it could convey the
> > meaning we need.
> >
> > And there is such a keyword: return.
> >
> > int return monkey;
> >
> > This would probably require that the keyword not appear in the first position,
> > so as to not be confused for a return statement.
> >
>
> What is the point of any keyword or anything else there?
> why code like:
> ```
> Mutex m;
> return m;
> ```
> could not work out of the box? We only need prepare wording
> when we can use and return local objects that
> are not movable. And If I recall correctly most of this
> work is done for movable types.

This was discussed in the actual proposal for this functionality
(P2025). The conclusion of the committee
(https://github.com/cplusplus/papers/issues/756) was:

> This paper needs to explore an explicit opt-in syntax and return to EWG.

The reasoning isn't stated, but given all of the cases listed in the
proposal where doing a particular thing that is not local to the
variable declaration or return statement shuts off elision, the most
obvious reason to me is that... you cannot non-locally change the
meaning of code. If you declare a named return variable, then all of
those cases that shut off elision non-locally are *compile errors*,
not potentially silent breakage.

Consider this:

```
template<typename T>
T supposed_nrvo()
{
  T t(...);
  if(some_condition) return {...};
  return t;
}
```

If you intend this to do NRVO, then according to P2025's rules, this
won't actually work. But it is still 100% legitimate code, and it will
work for any `T` that is copyable or moveable. So your code will
*appear* to be correct... right up until someone passes a non-moveable
`T` and then it breaks. So I hope you remembered to test for that
particular circumstance.

By contrast:

```
template<typename T>
T supposed_nrvo()
{
  return_value T t(...);
  if(some_condition) return {...};
  return t;
}
```

This is a compile error regardless of the nature of `T`, as it should
be. By declaring your intent to declare a named return value object,
you have also declared that you will not do anything that would
prevent that variable from being the object that will be returned from
this function. Like returning a different object.

Received on 2023-08-12 16:33:08