C++ Logo

std-proposals

Advanced search

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

From: Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>
Date: Sun, 16 Jul 2023 10:53:22 +0100
On Sun, Jul 16, 2023 at 1:26 AM Jason McKesson via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> I doubt that returning locked mutexes is the kind of example that
> would change their minds.


I've made it generic, so maybe they're more interested in returning a
decremented semaphore or a true atomic_flag?

      https://godbolt.org/z/6j3bKcYGd

I could have simplified it more by making combining the 'create' and
'manipulate' into one function. Or alternatively I could have gotten
rid of the programmer's use of 'placement new' by having the
programmer just give me a typename (and then I do the placement new
behind the scenes for them).

If the Standards Committee isn't keen on giving us guaranteed elision
for NRVO, then maybe a compromise would be to put a template function
something like the following in the Standard Library?

I might actually implement this template function on half a dozen
different architectures and then put it in a paper. Next I'll do
Microsoft x64.

And here it is copy-pasted:

#include <mutex> // mutex
#include <type_traits> // remove_cvref_t
#include <new> // placement 'new'

#include <iostream> // ------- just for testing -------

struct Mutex {
    // ---------- cannot move and cannot copy ----------
    Mutex(Mutex &&) = delete;
    Mutex(Mutex const & ) = delete;

    Mutex(void) { std::cout << "construct\n"; }
    void lock(void) { std::cout << "lock\n" ; }
    void unlock(void) { std::cout << "unlock\n" ; }
    ~Mutex(void) { std::cout << "destroy\n" ; }
};

extern "C" void Func(void);

__asm("Func: \n"
      ".intel_syntax noprefix \n"
      " push rdi \n" // save to restore later
      " push rsi \n" // save to restore later
      " push rdx \n" // save to restore later
      " call rsi \n" // call constructor
      " pop rdx \n" // restore after call
      " pop rsi \n" // restore after call
      " pop rdi \n" // restore after call
      " call rdx \n" // call manipulator
      " ret \n"
      ".att_syntax");

template<typename T>
std::remove_cvref_t<T> FuncT( void (*const
create)(std::remove_cvref_t<T>*), void (*const
manipulate)(std::remove_cvref_t<T>*) )
{
    typedef decltype(FuncT<Mutex>) *FuncPtr;
    FuncPtr const f = reinterpret_cast<FuncPtr>( Func );
    return f(create,manipulate);
}

// ==================================== And now the test code:

int main(void)
{
    auto retval = FuncT<Mutex>(
        [](Mutex *const p) { ::new(p) Mutex(); },
        [](Mutex *const p) { p->lock(); } );

    // Func has returned a locked mutex by value!

    retval.unlock();
}

Received on 2023-07-16 09:53:32