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 13:20:20 +0100
On Sun, Jul 16, 2023 at 12:54 PM Frederick Virchanza Gotham
<cauldwell.thomas_at_[hidden]> wrote:
>
> For the time being I will
> re-write the code to accommodate lambdas-with-captures by using
> "std::function<void(void*)>" instead of function pointers.


I have it working with "std::function" now, and so we can use
lambdas-with-captures:

    https://godbolt.org/z/6788exab5

Ok now I'm going to write a function that can put this
returned-by-value-locked-mutex inside an std::optional.

And copy-pasted:

#include <new> // placement 'new'
#include <functional> // function
#include <type_traits> // remove_cvref_t
#include <iostream> // ------- just for testing -------

extern "C" void InvokeFunctional(void *const p,
std::function<void(void*)> const &f)
{
    if ( f ) f(p);
}

struct Mutex {
    // ---------- cannot move and cannot copy ----------
    Mutex(Mutex &&) = delete;
    Mutex(Mutex const & ) = delete;
    Mutex &operator=(Mutex &&) = delete;
    Mutex &operator=(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 rsi \n" // save to restore later
      " push rdi \n" // save to restore later
      " push rdx \n" // save to restore later
      " call InvokeFunctional \n" // call 'create'
      " pop rdx \n" // restore after call
      " pop rdi \n" // restore after call
      " mov rsi, rdx \n" // Move 3rd argument to 2nd
      " call InvokeFunctional \n" // call 'manipulate'
      " pop rsi \n" // restore after call
      " ret \n"
      ".att_syntax");

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

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

int main(int const argc, char **const argv)
{
    auto retval = FuncT<Mutex>(
        [](Mutex *const p) { ::new(p) Mutex(); },
        [argc](Mutex *const p) { if ( argc % 2 ) p->lock(); } );

    // Func has returned a locked mutex by value!

    retval.unlock();
}

Received on 2023-07-16 12:20:30