C++ Logo

liaison

Advanced search

Re: [wg14/wg21 liaison] [isocpp-sg21] Telecon to review P2388R1 Minimum Contract Support: either Ignore or Check_and_abort

From: Ville Voutilainen <ville.voutilainen_at_[hidden]>
Date: Mon, 27 Sep 2021 10:27:50 +0300
On Mon, 27 Sept 2021 at 10:03, Jā‚‘ā‚™ā‚› Gustedt <jens.gustedt_at_[hidden]> wrote:
> > Since this "lambda" isn't callable by other parts of the program, this
> > looks like something that C should be able to express, too.
> > It's less consistent with the current lambda proposals in C due to
> > those not having all the bells and whistles, but, oh well.
>
> This triggers my interest ;-)
>
> First, I think that using lambas as proposed in the draft seems really
> a smart idea. This is a good step forward.
>
> The missing thing that you are refering to is initialization of
> reference/lvalue captures?

Yes. C++ lambdas have init-captures, I'm unaware of any attempt for C
lambdas to have them.

> AFAICS this is only necessary for the very specific feature of naming
> a return value. So this would not be in conflict with the lambda
> approach for C, where I tried just to be very careful not to introduce
> aliasing to existing objects. Any "capture-like" syntax that just
> gives a name and type to the return value/object, even as the proposed
> `&name=return` looks good to me.

It's more than just naming a return value; an init-capture allows you
to perform an arbitrary
transformation for how a capture is initialized. With it, you could
dig inside a smart pointer and initialize
a capture from the smart pointer's internal data even if the smart
pointer itself isn't copyable.
As an example, I can capture an int out of a smart pointer to int,
https://wandbox.org/permlink/iWerXYkCC9SwD81f
or as a more barebones example, I can capture an int out of a pointer to int,
https://wandbox.org/permlink/c9fP2pr6nCnfAmsQ

So, with this lambda-like precondition/postcondition facility, I can
traverse object graphs in the 'init-capture',
and save whatever values I like for later comparison by a
postcondition expression, for instance.
I can express a postcondition that says "the function returns
something that is less than the value the argument
pointed to at the point of call", and the function can change what the
argument pointed to without changing
what the postcondition means. Meaning that I can have a postcondition
expressed in terms of what the incoming
values were even if the incoming values are later indirectly written
to by the function.

The whole reason for the const-restriction in postconditions of the
current proposal is because of this, allowing writes would prevent
expressing postconditions in the terms of the incoming values, because
the function could change the values
and the original incoming values would be lost. Saving them has a
cost, and depending on the parameter types,
doesn't work the same way for all types (C++ has move-only types that
can't be copied, and you can't have a 'saved'
value of a move-only type that's available both for the postcondition
and for the function itself). Being able to
init-capture the original value solves this problem. I can even "copy"
an incoming move-only value like a unique_ptr
by doing an init-capture of a new allocation created from the object
pointed-to. I can just copy the underlying int.
I can do whatever I like with an init-capture, and I can decide
whether I capture by value, by reference, or by
arbitrary transformation. This removes all limitations of what
postconditions I can write and what the function
is allowed to do to/via/through the parameter.

Received on 2021-09-27 02:28:04