C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::elide

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Mon, 20 May 2024 14:50:19 +0100
On 20/05/2024 14:24, Brian Bi wrote:
>
>
> On Mon, May 20, 2024, 8:34 AM Lénárd Szolnoki via Std-Proposals
> <std-proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>>
> wrote:
>
>
>
>
> On 19/05/2024 21:28, Frederick Virchanza Gotham via Std-Proposals wrote:
> > On Sunday, May 19, 2024, Jason McKesson wrote:
> >>
> >> Then you haven't actually fixed the problem, have you? If you
> believe
> >> that the standard needs a way to do NRVO, then providing a "way
> to do
> >> NRVO" that doesn't represent legal C++ code is not actually
> fixing the
> >> problem.
> >
> >
> > Well you can make it all legal C++ code if you tinker with the object
> > files instead of the C++ source files. For example I can write the
> > following function:
> >
> > void Func(void *const p)
> > {
> > auto &m = *::new(p) mutex{};
> > try
> > {
> > m.lock();
> > }
> > catch(...)
> > {
> > m.~mutex();
> > throw;
> > }
> > }
> >
> > And compile it to an object file which will export the following
> > symbol: _Z4FuncPv
> >
> > Then all you need to do is use 'objcopy' (or a hex editor) to rename
> > that symbol to: _Z4Funcv
> >
> > And now it behaves as though you had written:
> >
> > mutex Func(void)
> > {
> > mutex m;
> > m.lock();
> > return m;
> > }
> >
> > And then in a separate translation unit, you declare the function as:
> > extern mutex Func(void);
> > Or . . . to make things even simpler, just define the function as
> > "extern C" and then you don't have to change the linker symbol as it
> > will simply be "Func".
> >
> > As fun and interesting as this back-and-forth is, Jason, let's get to
> > the crux of the matter. There's already a lengthy paper to provide
> > NRVO:
> >
> >
> https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2025r2.html <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2025r2.html>
> >
> > This paper has been gathering dust for 3 years (actually a few more
> > than that if you consider the previous revisions), and it's not
> > because it's a bad paper. I think it hasn't had any thrust behind it
> > because it's just too much grief to write it into the Standard
> and for
> > compiler vendors to implement it. So if P2025 is going to gather dust
> > past C++26, C++29, C++32 and so on, then how about we just try
> > something less ambitious.
>
> I think it's a great paper, and I think it's gathering dust for much
> more banal reasons, like the original author not having the time or
> motivation to update it, somebody else to have the motivation to
> pick it up.
>
>
> I would have been interested in picking it up, but I looked at the
> minutes and the reflector discussion and it seemed like there were
> significant implementability challenges that are difficult for me to
> even understand.
>
> Do we even know whether the proposed direction was actually viable?

Good question, maybe if that's what the pushback is on then implementing
it in clang as a vendor-extension could move it forward. Add a
[[clang::nrvo]] attribute on the variable you want to force nrvo on. It
also takes care of the opt-in, but for the standardization this
shouldn't be an attribute IMO.

>
> I personally think it's a great paper, but one of the short-coming is
> that it should require an opt-in syntax for NRVO, and that invites the
> inevitable bikeshedding around syntax that can destroy any remaining
> motivation from paper authors.
>
> > A less-ambitious alternative would be to
> > allow something like:
> >
> > mutex Func(void)
> > {
> > auto &m = _Retvar{};
> > m.lock();
> > return _Retvar;
> > }
> >
> > I propose that the operator "_Retvar" can only be used in a function
> > that returns by value. Its job is to create an object of the return
> > type, and it returns a reference to the new object. Then later you
> > just write "return _Retvar" to return from the function.
>
> I think if you are going to propose a barebones solution with many
> undefined behavior traps, than what should be done is to just expose
> the
> return slot to the function body as storage, without automatically
> constructing anything there. Then it's the responsibility of the
> function to populate the return slot, if the function exits by
> exception
> or to ensure that the return slot is empty, if it exits by exception.
>
> I'm not a huge fan of this, because it's easy to misuse compared P2025,
> which is already very flexible, but arguably this is simpler to
> implement.
>
> Anyway, some food for thought: functions can and do reuse the return
> slot multiple times, P2025 also allows this:
>
> Widget foo(string some_arg) {
> {
> Widget widget(some_arg); // widget is created on return slot
> if (widget.check_something()) {
> return widget; // return normally...
> }
> } //... or destroy widget
> return Widget("default"); // and return an entirely different object
> }
>
> IME clang optimizes this to use NRVO for `widget`, gcc does not.
>
> So the return slot's occupancy can be on and off throughout the
> execution of the function.
>
> Cheers,
> Lénárd
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden] <mailto:Std-Proposals_at_[hidden]>
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
> <https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals>
>

Received on 2024-05-20 13:50:21