Date: Thu, 14 Sep 2023 10:31:54 +0200
An alternative would be to declare the name (alias) for the return value:
auto lockedMutexFactory() -> std::mutex m {
m.lock();
return m; // Either: only m allowed here, or,
// return std::mutex(); // alternatively, the destructor of m is called
first,
// and then std::mutex() is returned
}
On Thu, Sep 14, 2023 at 12:33 AM Sebastian Wittmeier via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> Hi Arthur,
>
> so let us focus on the factory function. The value semantics code has to
> produce the pointer semantics code somehow out of value syntax.
>
>
>
> I think it is useful to explicitly mark the returned variable at
> declaration, as it is located in the memory of the caller. Even if the
> compiler can deduce it from the returned expression.
>
> This is better than marking it (only) at the return IMHO.
>
>
>
> std::mutex lockedMutexFactory() {
>
> std::mutex return m; // mark the variable with return keyword;
>
> // it is not constructed on the stack,
>
> // but at the location provided by the caller
>
> m.lock();
>
> return m; // Either: only m allowed here, or,
>
> // return std::mutex(); // alternatively, the destructor of m is
> called first,
>
> // and then std::mutex() is returned
>
> }
>
> The variable marked with 'return' should be of the same type as the
> function return type.
>
> There can be only one variable marked as 'return' (but they can have
> different names in parallel code blocks, e.g. in the if and the else block).
>
> Each path out of the function (return, throw, ...) either uses the
> existing marked variable, destructs it and/or creates a new object at that
> caller-provided location or does nothing.
>
>
>
> Best,
>
> Sebastian
>
>
>
> -----Ursprüngliche Nachricht-----
> *Von:* Arthur O‘Dwyer via Std-Proposals <std-proposals_at_[hidden]>
> *Gesendet:* Mi 13.09.2023 17:19
> *Betreff:* Re: [std-proposals] Copy-construct, move-construct, and
> PR-construct
> *An:* std-proposals_at_[hidden];
> *CC:* Arthur O‘Dwyer <arthur.j.odwyer_at_[hidden]>;
> On Tue, Sep 12, 2023 at 2:16 PM Sebastian Wittmeier via Std-Proposals <
> std-proposals_at_[hidden]> 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
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
auto lockedMutexFactory() -> std::mutex m {
m.lock();
return m; // Either: only m allowed here, or,
// return std::mutex(); // alternatively, the destructor of m is called
first,
// and then std::mutex() is returned
}
On Thu, Sep 14, 2023 at 12:33 AM Sebastian Wittmeier via Std-Proposals <
std-proposals_at_[hidden]> wrote:
> Hi Arthur,
>
> so let us focus on the factory function. The value semantics code has to
> produce the pointer semantics code somehow out of value syntax.
>
>
>
> I think it is useful to explicitly mark the returned variable at
> declaration, as it is located in the memory of the caller. Even if the
> compiler can deduce it from the returned expression.
>
> This is better than marking it (only) at the return IMHO.
>
>
>
> std::mutex lockedMutexFactory() {
>
> std::mutex return m; // mark the variable with return keyword;
>
> // it is not constructed on the stack,
>
> // but at the location provided by the caller
>
> m.lock();
>
> return m; // Either: only m allowed here, or,
>
> // return std::mutex(); // alternatively, the destructor of m is
> called first,
>
> // and then std::mutex() is returned
>
> }
>
> The variable marked with 'return' should be of the same type as the
> function return type.
>
> There can be only one variable marked as 'return' (but they can have
> different names in parallel code blocks, e.g. in the if and the else block).
>
> Each path out of the function (return, throw, ...) either uses the
> existing marked variable, destructs it and/or creates a new object at that
> caller-provided location or does nothing.
>
>
>
> Best,
>
> Sebastian
>
>
>
> -----Ursprüngliche Nachricht-----
> *Von:* Arthur O‘Dwyer via Std-Proposals <std-proposals_at_[hidden]>
> *Gesendet:* Mi 13.09.2023 17:19
> *Betreff:* Re: [std-proposals] Copy-construct, move-construct, and
> PR-construct
> *An:* std-proposals_at_[hidden];
> *CC:* Arthur O‘Dwyer <arthur.j.odwyer_at_[hidden]>;
> On Tue, Sep 12, 2023 at 2:16 PM Sebastian Wittmeier via Std-Proposals <
> std-proposals_at_[hidden]> 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
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2023-09-14 08:32:07