you don't need external access to the data members and just want to benefit from RAII, you can convert the class to a coroutine that suspends itself right before ending:
class scope {
public:
struct promise_type {
scope get_return_object() noexcept {
return scope { std::coroutine_handle<promise_type>::from_promise(*this) };
}
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_always final_suspend() noexcept { return {}; }
void return_void() noexcept {}
void unhandled_exception() { std::terminate(); }
};
...
~scope() {
if (!this->handle) return;
this->handle.destroy();
this->handle = {};
}
private:
explicit scope(std::coroutine_handle<promise_type> h) noexcept : handle(h) {}
std::coroutine_handle<promise_type> handle {};
};
scope gpio_uart_forwarder() {
auto gpio_in = peripheral::gpio {};
auto gpio_out = peripheral::gpio {};
auto uart = peripheral::uart {};
auto gpio_to_uart = evt::callback { gpio_in.on_change, [&](bool high) {
uart.write(high ? '1' : '0');
} };
auto uart_to_gpio = evt::callback { uart.on_char, [&](char c) {
if (c == '1') gpio_out.set(1);
else if (c == '0') gpio_out.set(0);
} };
// All local variables remain alive until coroutine is destroyed
co_await std::suspend_always();
// Can't rely on final_suspend because stack is already destroyed by then
// But we need a co_ statement anyway to turn it into a coroutine
}
scope my_gpio_uart_forwarder = gpio_uart_forwarder();
Far from perfect, but it reduces us to a single heap allocation plus the minimal overhead of launching the coroutine, no matter how many callbacks we define.
Maybe the best part is it can be used *within* an existing class too, preserving standard object RAII:
struct gpio_uart_forwarder {
peripheral::gpio gpio_in {};
peripheral::gpio gpio_out {};
peripheral::uart uart {};
scope callbacks = [&] -> scope {
auto gpio_to_uart = evt::callback { gpio_in.on_change, [&](bool high) {
uart.write(high ? '1' : '0');
} };
auto uart_to_gpio = evt::callback { uart.on_char, [&](char c) {
if (c == '1') gpio_out.set(1);
else if (c == '0') gpio_out.set(0);
} };
co_await std::suspend_always();
}();
}
https://redd.it/1tg6mzu
@r_cpp
Post #25209
14