C++ Logo

std-proposals

Advanced search

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

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Sun, 16 Jul 2023 12:09:37 -0400
On Sun, Jul 16, 2023 at 11:58 AM Jens Maurer via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On 16/07/2023 17.39, Frederick Virchanza Gotham via Std-Proposals wrote:
> > I reply to Jason and Arthur in series below.
> [...]
> I don't like having this as a magic library function with plenty of
> callbacks. If this is worth having in the standard, let's make sure
> the core language offers the relevant facility.
>
> (Being able to manually cause the named return value optimization
> might be helpful beyond returning locked mutexes.)
>

Hear, hear.
Here's a version without inline assembly but still using "unnatural
intimacy with the (Itanium) ABI":
https://godbolt.org/z/53e6eE3W7
The problem with this — and with the inline-assembly stuff — is that it's
not portable C++. In fact, my version is so unportable that GCC barfs at
-O1: it sees that we're reinterpret_cast'ing a function pointer to the
"wrong" function type and then calling through it, which is UB, so it
eliminates everything after that point.

This is tantalizingly similar, but not really the same, as something I just
re-raised on the SG14 mailing list:

[...] a pair of attributes to stick on a variable: [[no_construct]], to
> skip the constructor but still destroy the variable at end-of-scope as
> usual; and [[no_destroy]] to do the constructor but skip the destructor.
> Clang and GCC both support [[no_destroy]]
> <https://clang.llvm.org/docs/AttributeReference.html#no-destroy>, but
> only on static and thread-local storage.
> Nobody supports [[no_construct]] yet.
> But I know about these attributes because *if we had them for stack
> variables* then the vendor could implement P1144 `T std::relocate(T*)`
> without intimate knowledge
> <https://quuxplusone.github.io/blog/2022/05/18/std-relocate/> of the
> calling convention:
> template<class T>
> T relocate(T *src) {
> if constexpr (std::is_trivially_relocatable_v<T>) {
> [[do_not_construct]] T dst;
> std::relocate_at(src, &dst); // construct dst and destroy src, as
> if by memcpy
> return dst; // but still get the benefit of NRVO here
> } else {
> T dst = T(std::move(*src));
> std::destroy_at(src);
> return dst; // get the benefit of NRVO here
> }
> }


Notice I'm saying "still get the benefit of NRVO," but of course we still
get NRVO only for movable types (because immovable types like `mutex` can't
be NRVO'ed in the first place). So maybe these problems are not *close
together* but *orthogonal*. :) Still, they're both in the same area — and
the same area is also currently being explored by the various "non-trivial
relocation" papers in the Varna mailing.

Cheers,
Arthur

Received on 2023-07-16 16:09:50