On Tue, Sep 12, 2023 at 2:16 PM Sebastian Wittmeier via Std-Proposals <std-proposals@lists.isocpp.org> wrote:

Should we have unmovable-and-uncopiable return values at all?

 

Even if it can be technically solved for certain cases, those classes are not meant to be moved, copied or returned.


s/or returned//
I'd say that such types were always meant to be supported (because why wouldn't they be?), and since C++17 immovable return types have been supported, at least in the cases that Just Work (like `return std::mutex();`). One certainly can't say that std::mutex wasn't "meant" to be returned. It's a class type; of course you can return it from a function! (In spirit, although not literally, each constructor of std::mutex is such a function.)
 

Better change the interface of std::optional::emplace and/or SomeFunctionThatReturnsMutex().

So that

 - SomeFunctionThatReturnsMutex gets a pointer, where to construct its mutex and

 - emplace gets a Callable, which creates the mutex at the right moment in time


The problem with that kind of "two-stage initialization" is that it doesn't lend itself to value semantics. You're suggesting that I should write
    std::mutex *lockedMutexFactory(void *where) { auto *p = ::new (where) std::mutex(); p->lock(); return p; }
    alignas(std::mutex) char buf[sizeof(std::mutex)];
    std::mutex *m = lockedMutexFactory(buf);
    use(*m);
    m->~mutex();
but what I really want to write is
    std::mutex lockedMutexFactory() { std::mutex m; m.lock(); return /*somehow*/ m; }
    use(lockedMutexFactory());

Now, I don't think any of the half-proposed ideas in this thread so far have been good.
But I disagree with the notion that we should somehow desire two-stage initialization just because one of our types happens to be immovable.

FVG wrote:
   optional<mutex> om;

   om.emplace( SomeFunctionThatReturnsMutex() );

Currently we can't do this, and it's something that needs to change.
We can do this fine; use the SCSE pattern.
The things we currently can't do are:
- Implement SomeFunctionThatReturnsMutex() in the first place, unless it's happy with URVO (i.e. just calls a ctor, or another factory, and does nothing else before returning)
- Do this dance for a hypothetical immovable type that is convertible-from any T

my $.02,
Arthur