octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: error with d28016d16e9a (change to jsonencode.cc)


From: Rik
Subject: Re: error with d28016d16e9a (change to jsonencode.cc)
Date: Thu, 1 Oct 2020 17:13:04 -0700

On 10/01/2020 12:42 PM, John W. Eaton wrote:
On 10/1/20 2:33 PM, Rik wrote:

"should work", but needs to be checked.  The first lambda _expression_ I wrote for Octave would not work with capture which is why I used the parameter-passing approach.

Do you remember what it was that didn't work?

I don't.  It might work now that we've switched to unwind_action rather than unwind_protect objects.


Except for "this", lambdas capture by value by default.  Capturing "this" allows access to the current object, so instead of writing

  unwind_action restore_scope
    ([] (auto self) { self->pop (); }, this);

we can write

  unwind_action restore_scope ([this] (void) { pop (); });

and instead of

  unwind_action executing_callbacks_cleanup
    ([] (auto old_callback_props, auto &self)
     { old_callback_props->erase (self); }, &executing_callbacks, this);

we can write

  unwind_action executing_callbacks_cleanup
    ([this] () { executing_callbacks.erase (this); });

In this last case, "executing_callbacks" is also a file-scope static variable, so the lambda can access it directly without capture.

I like these as even simpler, less verbose forms.


We could also decide to always use "[=]" when we need to capture something.  Then all variables that are needed, including "this" will be captured using the default rules for capture by value.

I don't think this is recommended practice.  The temporary anonymous struct that is created to represent the lambda _expression_ will then have an argument in the constructor for every existing variable in the surrounding function.  The compiler *might* then optimize out all of the additional unused captures, but I think it would be better to just capture what you need either by value "[=variable_name]" if small like a built-in type or a pointer or by reference "[&variable_name]" if it is something large like the instance of a class.  For reference, I was using this https://dzone.com/articles/all-about-lambda-functions-in-cfrom-c11-to-c17.


The unwind_action + lambda _expression_ feature is definitely complicated and has a lot of options for how to use it.  There's no one right way. I'd just like to agree on a set of guidelines to make it as simple as possible to write, understand, and maintain.  My first pass at that would be

  * when possible, capture variables by value directly in the lambda _expression_ instead of the unwind_action object

I would modify this to only small values should be passed by value.


  * use lambda _expression_ arguments and capture values in the unwind_action object only when necessary (for example, when the value is not a variable in the local scope)

This seems like a good convention to adopt.


and possibly

  * use "[=]" to capture local variables and avoid the redundancy of explicitly writing the list of captured variables since they will already appear in the lambda _expression_ anyway

I would skip this as noted above.

--Rik


and, once we can move to C++14, maybe also add

  * use "auto" for lambda _expression_ argument declarations

jwe





reply via email to

[Prev in Thread] Current Thread [Next in Thread]