C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::elide

From: Lee Howes <xrikcus_at_[hidden]>
Date: Fri, 24 May 2024 14:03:46 -0700
I don't think std::elide makes sense, but as you asked:
> While I can understand RVO, mutexes has got to be the worst possible
example for an application of this.
> It should just simply never happen in real code ever.
> I have posed this question before but got ignored, but it is crucial to
the point.

as part of this discussion I wanted to give a practical example.

I think you are limiting what you can imagine here by assuming that the
std::mutex alone is what the function would return. RVOing an object that
contains a mutex, along with a set of functions that would apply to that
mutex, is a perfectly sensible thing to do.

For example, I believe that this line RVOs a std::mutex:
https://github.com/facebookexperimental/libunifex/blob/8fd4b0cec7ce5b73fe48c2b78a5dd647121a4f51/include/unifex/new_thread_context.hpp#L89

Mutexes are probably not very common, but it's entirely reasonable to have
a mutex as part of an async operation. Take synchronizing a collect, for
example, a mutex might be the simplest solution. Unifex (and stdexec) will
embed objects like that in immovable objects that are located at known
addresses and can contain nested objects at known addresses.


I have a whole codebase heavily used in production here that relies on RVO
of immovable objects for correctness and efficiency. There have been
numerous cases where NRVO would make writing that code simpler, but
workarounds by wrapping in functions can always be made to work. Returning
a locked mutex would be strange, but I imagine should work in the same
sense that returning an object containing the mutex and an object
constructed with a reference to that mutex should work:
> struct Mut {Mut() : mref{m}{} std::mutex m; std::mutex& mref; /*delete
moves & copies*/};
> return Mut{};

returning an initialized atomic at a known location is probably a more
practical version of the locked mutex:
> struct At {At() : a{3}, aref{a}{} std::atomic<int> a; std::atomic<int>&
aref; /*delete moves & copies*/};
> return At{};

Lee

Received on 2024-05-24 21:04:00