user2967: My C++ is very out-of-date. (20+ years, before C++ had closures).
I'm a senior SW engineer, and I spent several hours yesterday trying to figure this out, but I could not work it out.
The background:
I'm trying to create a class, ClosureButton, that is a subclass of another class, ArduinoObject. (An ArduinoObject has setup(), start(), stop(), and loop() methods so that the main program can invoke it.)
(C++ uses the terms closure and lambda to mean different things. In other languages the terms are interchangeable. Forgive me if I'm not using the correct term.)
A ClosureButton's constructor would take a pin number, and a closure with a bool parameter (pressed). I would save that closure to a member variable. When the button's state changed, it would invoke the closure and pass the new button state to the closure.
The question:
I need help with the syntax for the constructor, as well as how to declare the instance variable that would hold the closure.
The constructor would look something like this:
ClosureButton::ClosureButton(uint8_t pin, _unkonwn_syntax_ closure);

(Where I need help with the _unkonwn_syntax_ bit.)
Then I need to declare a member variable on my ClosureButton to hold the closure:
class ClosureButton: ArduinoObject {
  //other stuff
  _other_unkonwn_syntax_ closure;
}

Again, I need help with the syntax to declare a member variable closure of type "closure that takes a bool parameter". (The _other_unkonwn_syntax_ bit.) At this point I don't think my closure will capture variables from its enclosing scope, but at some future date I might need to do that, so help with that would be appreciated as well.)

user7508: I suggested in a comment that a functor may be a viable alternative to a
capturing lambda. This answer is mostly meant to answer the OP's request
to elaborate on that suggestion.
Let's define a ButtonCallback as an object that can be called like a
function taking a single boolean parameter:
class ButtonCallback {
public:
    virtual void operator()(bool) = 0;
};

To break down the syntax:

void operator()(bool) declares a method that allows the object to be
called as if it were a function taking a bool argument and returning
nothing. In other words, if you issue a call such as
my_object(true), that method will be called.
virtual _method_declaration_ = 0; says that the method is not going
to be defined for this class (it's a “pure virtual method”), but it
can be defined by derived classes. A class with such a method is
called an “abstract class”: it defines an interface, it cannot be
instantiated, and it's meant to be used as a parent for classes that
do implement the missing methods.

Now the Button class can be defined like this:
class Button {
public:
    Button(uint8_t pin, ButtonCallback &callback)
    : pin(pin), callback(callback) {}
    void push() {  // for testing only
        Serial.print("press: ");   callback(true);
        Serial.print("release: "); callback(false);
    }
private:
    uint8_t pin;
    ButtonCallback &callback;
};

Notice that the callback is stored as a reference to a
ButtonCallback object. The object itself cannot be stored because it
has an abstract type. Alternatively, a pointer could be used, which
would practically be equivalent.
For using this class, you first have to create the callback as a
concrete class that inherits from from ButtonCallback. Any data you
wish to capture should be stored as class data:
class CapturingLambda : public ButtonCallback {
public:
    CapturingLambda(int data) : some_data(data) {}
    virtual void operator()(bool pressed) {
        if (pressed)
            Serial.println(some_data);
        else
            Serial.println(0);
    }
private:
    int some_data;
};

With all this in place, the following test:
void setup() {
    Serial.begin(9600);
    int data_to_capture = 42;
    CapturingLambda callback(data_to_capture);
    Button the_button(2, callback);
    the_button.push();
}

void loop(){}

outputs:
press: 42
release: 0

Did you said you “find the syntax of C++ pretty obtuse”? I can only
concur with you!

Addendum: Another alternative is to define the callback using the
good old C idiom: a “lambda” is the combination of a function pointer
and a generic data pointer. The function pointer looks like this:
typedef void (*ButtonCallback)(bool, void *);

The second argument is used to provide the callback whatever data it is
supposed to have “captured”. It is a generic pointer (a void *)
because the library does not know what kind of data its client may need.
Now the Button class has to store both the function pointer and the
data pointer, and always provide the data pointer to the callback:
class Button {
public:
    Button(uint8_t pin, ButtonCallback callback, void *callback_data)
    : pin(pin), callback(callback), callback_data(callback_data) {}
    void push() {  // for testing only
        Serial.print("press: ");   callback(true, callback_data);
        Serial.print("release: "); callback(false, callback_data);
    }
private:
    uint8_t pin;
    ButtonCallback callback;
    void *callback_data;
};

The user would have to decide what kind of data it needs, and do
explicit pointer casts to/from the proper pointer type and void *. For
example, assuming we need an int, the callback may be:
void callback(bool pressed, void *data) {
    int *actual_data = (int *) data;
    if (pressed)
        Serial.println(*actual_data);
    else
        Serial.println(0);
}

Here is the test, with the exact same output as before:
void setup() {
    Serial.begin(9600);
    int data_to_capture = 42;
    Button the_button(2, callback, (void *) &data_to_capture);
    the_button.push();
}

void loop(){}

Notice that, syntactic differences apart, this solution does essentially
the same as the previous one. The main difference is that the data is
given to the callback as an explicit pointer instead of the implicit
this pointer. If you have to choose between these two solutions, I
would suggest going for whichever syntax you find easier to work with.
Beware also that in both cases it is the programmer's responsibility to
manage the storage of the callback data and make sure the corresponding
reference (or pointer) remains valid throughout the lifetime of the
Button object.

user4143: There is no difference using a function pointer or a simple (non-capturing) lambda (C++ calls them lambdas).  The only difference is that you provide a lambda instead of a function pointer.
For example:
void (*func)(bool b);

void setup() {
    func = [](bool b) {
        Serial.println(b);
    };

    Serial.begin(115200);
}

void loop() {
    func(digitalRead(0));
}

It's just a normal function pointer, but instead of assigning a function pointer to it you assign a lambda to it - which is just an anonymous function pointer.
To make life easier you can make a typedef for your function pointer variable type:
typedef void (*buttonCallback)(bool);

Then your functions would look like:
ClosureButton::ClosureButton(uint8_t pin, buttonCallback closure);

and:
class ClosureButton: ArduinoObject {
  //other stuff
  buttonCallback closure;
}

The basic syntax of a lambda is quite straight forward:
[](bool foo, int bar) { ... }
^  ^                    ^
|  |                    +- Function body
|  +- Normal parameter list
+- Empty capture list

If you want to return a value and you don't want to rely on the function being an "auto" return type you can specify the return type after the parameter list:
[](bool foo, int bar)->int { ... }
^  ^                   ^     ^
|  |                   |     +- Function body
|  |                   +- Return type
|  +- Normal parameter list
+- Empty capture list

If you don't specify the return type it is inferred from the type of variable/value that is used with return (as if the function were auto).

Here's a full example passing the lambda to a class which stores the pointer to it in a variable to call later:
typedef int (*callback)(bool b);

class MyClass {
    private:
        callback func;
        int pin;

    public:
        MyClass(int pinno, callback myfunc) {
            func = myfunc;
            pin = pinno;
        }

        void doit() {
            Serial.println(func(digitalRead(pin)));
        }
};

MyClass foo(3, [](bool b)->int {
        Serial.println(b);
        return rand();
});


void setup() {
    pinMode(3, INPUT_PULLUP);
    Serial.begin(115200);
}

void loop() {
    foo.doit();
    delay(100);
}


If you want to do capturing with your lambdas then I'm afraid you're out of luck.
The data type for that kind has to be std::function<void> but unfortunately the cut-down C library AVR-LIBC doesn't support that. The STL is generally not included for small microcontrollers since it uses far too many resources to be practical.

2967: <p>My C++ is very out-of-date. (20+ years, before C++ <em>had</em> closures).</p>

<p>I'm a senior SW engineer, and I spent several hours yesterday trying to figure this out, but I could not work it out.</p>

<p><strong>The background:</strong></p>

<p>I'm trying to create a class, <code>ClosureButton</code>, that is a subclass of another class, <code>ArduinoObject</code>. (An <code>ArduinoObject</code> has <code>setup()</code>, <code>start()</code>, <code>stop()</code>, and <code>loop()</code> methods so that the main program can invoke it.)</p>

<p>(C++ uses the terms closure and lambda to mean different things. In other languages the terms are interchangeable. Forgive me if I'm not using the correct term.)</p>

<p>A ClosureButton's constructor would take a pin number, and a closure with a bool parameter (<code>pressed</code>). I would save that closure to a member variable. When the button's state changed, it would invoke the closure and pass the new button state to the closure.</p>

<p><strong>The question:</strong></p>

<p>I need help with the syntax for the constructor, as well as how to declare the instance variable that would hold the closure.</p>

<p>The constructor would look something like this:</p>

<pre><code>ClosureButton::ClosureButton(uint8_t pin, _unkonwn_syntax_ closure);
</code></pre>

<p>(Where I need help with the <code>_unkonwn_syntax_</code> bit.)</p>

<p>Then I need to declare a member variable on my ClosureButton to hold the closure:</p>

<pre><code>class ClosureButton: ArduinoObject {
  //other stuff
  _other_unkonwn_syntax_ closure;
}
</code></pre>

<p>Again, I need help with the syntax to declare a member variable <code>closure</code> of type "closure that takes a bool parameter". (The <code>_other_unkonwn_syntax_</code> bit.) At this point I don't think my closure will capture variables from its enclosing scope, but at some future date I might need to do that, so help with that would be appreciated as well.)</p>
 7508: <p>I suggested in a comment that a functor may be a viable alternative to a
capturing lambda. This answer is mostly meant to answer the OP's request
to elaborate on that suggestion.</p>

<p>Let's define a <code>ButtonCallback</code> as an object that can be called like a
function taking a single boolean parameter:</p>

<pre><code>class ButtonCallback {
public:
    virtual void operator()(bool) = 0;
};
</code></pre>

<p>To break down the syntax:</p>

<ul>
<li><code>void operator()(bool)</code> declares a method that allows the object to be
called as if it were a function taking a <code>bool</code> argument and returning
nothing. In other words, if you issue a call such as
<code>my_object(true)</code>, that method will be called.</li>
<li><code>virtual _method_declaration_ = 0;</code> says that the method is not going
to be defined for this class (it's a “pure virtual method”), but it
can be defined by derived classes. A class with such a method is
called an “abstract class”: it defines an interface, it cannot be
instantiated, and it's meant to be used as a parent for classes that
do implement the missing methods.</li>
</ul>

<p>Now the <code>Button</code> class can be defined like this:</p>

<pre><code>class Button {
public:
    Button(uint8_t pin, ButtonCallback &amp;callback)
    : pin(pin), callback(callback) {}
    void push() {  // for testing only
        Serial.print("press: ");   callback(true);
        Serial.print("release: "); callback(false);
    }
private:
    uint8_t pin;
    ButtonCallback &amp;callback;
};
</code></pre>

<p>Notice that the callback is stored as a <em>reference</em> to a
<code>ButtonCallback</code> object. The object itself cannot be stored because it
has an abstract type. Alternatively, a pointer could be used, which
would practically be equivalent.</p>

<p>For using this class, you first have to create the callback as a
concrete class that inherits from from <code>ButtonCallback</code>. Any data you
wish to capture should be stored as class data:</p>

<pre><code>class CapturingLambda : public ButtonCallback {
public:
    CapturingLambda(int data) : some_data(data) {}
    virtual void operator()(bool pressed) {
        if (pressed)
            Serial.println(some_data);
        else
            Serial.println(0);
    }
private:
    int some_data;
};
</code></pre>

<p>With all this in place, the following test:</p>

<pre><code>void setup() {
    Serial.begin(9600);
    int data_to_capture = 42;
    CapturingLambda callback(data_to_capture);
    Button the_button(2, callback);
    the_button.push();
}

void loop(){}
</code></pre>

<p>outputs:</p>

<pre><code>press: 42
release: 0
</code></pre>

<p>Did you said you “find the syntax of C++ pretty obtuse”? I can only
concur with you!</p>

<hr>

<p><strong>Addendum</strong>: Another alternative is to define the callback using the
good old C idiom: a “lambda” is the combination of a function pointer
and a generic data pointer. The function pointer looks like this:</p>

<pre><code>typedef void (*ButtonCallback)(bool, void *);
</code></pre>

<p>The second argument is used to provide the callback whatever data it is
supposed to have “captured”. It is a generic pointer (a <code>void *</code>)
because the library does not know what kind of data its client may need.
Now the <code>Button</code> class has to store <em>both</em> the function pointer and the
data pointer, and always provide the data pointer to the callback:</p>

<pre><code>class Button {
public:
    Button(uint8_t pin, ButtonCallback callback, void *callback_data)
    : pin(pin), callback(callback), callback_data(callback_data) {}
    void push() {  // for testing only
        Serial.print("press: ");   callback(true, callback_data);
        Serial.print("release: "); callback(false, callback_data);
    }
private:
    uint8_t pin;
    ButtonCallback callback;
    void *callback_data;
};
</code></pre>

<p>The user would have to decide what kind of data it needs, and do
explicit pointer casts to/from the proper pointer type and <code>void *</code>. For
example, assuming we need an <code>int</code>, the callback may be:</p>

<pre><code>void callback(bool pressed, void *data) {
    int *actual_data = (int *) data;
    if (pressed)
        Serial.println(*actual_data);
    else
        Serial.println(0);
}
</code></pre>

<p>Here is the test, with the exact same output as before:</p>

<pre><code>void setup() {
    Serial.begin(9600);
    int data_to_capture = 42;
    Button the_button(2, callback, (void *) &amp;data_to_capture);
    the_button.push();
}

void loop(){}
</code></pre>

<p>Notice that, syntactic differences apart, this solution does essentially
the same as the previous one. The main difference is that the data is
given to the callback as an explicit pointer instead of the implicit
<code>this</code> pointer. If you have to choose between these two solutions, I
would suggest going for whichever syntax <em>you</em> find easier to work with.</p>

<p>Beware also that in both cases it is the programmer's responsibility to
manage the storage of the callback data and make sure the corresponding
reference (or pointer) remains valid throughout the lifetime of the
<code>Button</code> object.</p>
 4143: <p>There is no difference using a function pointer or a simple (non-capturing) lambda (C++ calls them lambdas).  The only difference is that you provide a lambda instead of a function pointer.</p>

<p>For example:</p>

<pre><code>void (*func)(bool b);

void setup() {
    func = [](bool b) {
        Serial.println(b);
    };

    Serial.begin(115200);
}

void loop() {
    func(digitalRead(0));
}
</code></pre>

<p>It's just a normal function pointer, but instead of assigning a function pointer to it you assign a lambda to it - which is just an anonymous function pointer.</p>

<p>To make life easier you can make a typedef for your function pointer variable type:</p>

<pre><code>typedef void (*buttonCallback)(bool);
</code></pre>

<p>Then your functions would look like:</p>

<pre><code>ClosureButton::ClosureButton(uint8_t pin, buttonCallback closure);
</code></pre>

<p>and:</p>

<pre><code>class ClosureButton: ArduinoObject {
  //other stuff
  buttonCallback closure;
}
</code></pre>

<p>The basic syntax of a lambda is quite straight forward:</p>

<pre><code>[](bool foo, int bar) { ... }
^  ^                    ^
|  |                    +- Function body
|  +- Normal parameter list
+- Empty capture list
</code></pre>

<p>If you want to return a value and you don't want to rely on the function being an "auto" return type you can specify the return type after the parameter list:</p>

<pre><code>[](bool foo, int bar)-&gt;int { ... }
^  ^                   ^     ^
|  |                   |     +- Function body
|  |                   +- Return type
|  +- Normal parameter list
+- Empty capture list
</code></pre>

<p>If you don't specify the return type it is inferred from the type of variable/value that is used with <code>return</code> (as if the function were <code>auto</code>).</p>

<hr>

<p>Here's a full example passing the lambda to a class which stores the pointer to it in a variable to call later:</p>

<pre><code>typedef int (*callback)(bool b);

class MyClass {
    private:
        callback func;
        int pin;

    public:
        MyClass(int pinno, callback myfunc) {
            func = myfunc;
            pin = pinno;
        }

        void doit() {
            Serial.println(func(digitalRead(pin)));
        }
};

MyClass foo(3, [](bool b)-&gt;int {
        Serial.println(b);
        return rand();
});


void setup() {
    pinMode(3, INPUT_PULLUP);
    Serial.begin(115200);
}

void loop() {
    foo.doit();
    delay(100);
}
</code></pre>

<hr>

<p>If you want to do capturing with your lambdas then I'm afraid you're out of luck.</p>

<p>The data type for that kind has to be <code>std::function&lt;void&gt;</code> but unfortunately the cut-down C library AVR-LIBC doesn't support that. The STL is generally not included for small microcontrollers since it uses far too many resources to be practical.</p>
