C++ Logo

std-proposals

Advanced search

Re: [std-proposals] std::elide

From: Lorand Szollosi <szollosi.lorand_at_[hidden]>
Date: Sat, 25 May 2024 01:30:12 +0200
Hi,

While returning something that decomposes to a locked mutex is indeed of
questionable direct use from my perspective as well, I think we're missing
the obvious (unless any fellow dev already stated):
struct getLockedMutex {
    std::mutex m;
    getLockedMutex() { m.lock(); }
};

Now, if we can set aside mutex for a while... Indeed, both 'returning
char[]' and 'non-movable object' came up this week at work, plus I'm
regularly working with handcrafted reflection. While this is not what I'm
here for, an object-oriented alloca() - or, if you prefer, annotations -
could hit these 3 birds with a stone. What I mean: expr1 @ expr2 could be
assigned the following meaning:
- type of expr1 @ expr2 is same as type of expr1
- throwing expr1 @ expr2 is the same as throwing expr1 (expr2 is not
evaluated)
- type of @(expr1 @ expr2) is same as expr2 and is allocated (in case of
ASDV):
    - when directly returning it, i.e., return expr1 @ expr2, in the
caller's scope, amongst ASDVs
        - returning expr1 @ expr2 requires either the function or lambda
specification to contain the annotation (in some form not yet decided at
the time of writing)
        - evaluation of expr2 in this case is scheduled-before destruction
of automatic storage duration variables in the function's scope (thus those
variables and function arguments are still available), but scheduled-after
evaluation of expr1
    - when accessing a member variable, in the scope where the access takes
place, amongst ASDVs
    - in any other context, in the current scope (but I'm okay with
caller's scope as well)
- when expr1 @ expr2, or a function that returns annotated, is directly
used as initializer in a definition of an ASDV, member variable, global
variable or function-local static variable a_var, (i.e., auto x = expr1 @
expr2; or struct S { int i = 1 @ "name-of-i-in-serialization"; }; ), both
the defined variable and the annotation are introduced, in this order.
    - evaluation takes place each time when the annotation @a_var is
accessed
- for expr1 @ expr2, in expr2, @@ is a reference to expr1 (the evaluation
of expr1 is sequenced-before the evaluation of expr2, so this is doable).
This allows for calling functions on the non-movable object being returned.

Note that the two names mean that a function call f(expr1 @ expr2) is still
the same as f(expr1), but a function returning annotated is to allocate in
caller's scope (hence the analogy to alloca) and, for member variables,
it's always evaluated when accessed. Thus, it brings us the infamous
post-constructor for returning non-movable object, some semi-manual
reflection/introspection for serialization-deserialization, the
ever-returning 'how to return char[]'; for some realistic use-cases, it'd
permit non-movable types with private ctor and named try-constructor
(static member function that returns std::optional<T> or std::expected<T,
E> because it might or might not fail for the arguments).

Obviously, @ and @@ are simply placeholders for any better syntax. Anyways,
this might work for the use-cases on this thread, but I'm rather off to my
old proposal, statement expressions, as that could bring some real value to
HFT I think...

Bests,
-lorro

Received on 2024-05-24 23:30:26