#include <iostream>
#include <memory>
struct function
{
struct base
{
virtual void call() = 0;
virtual base* clone() = 0;
};
template <typename Fn>
struct impl : base
{
Fn fn_;
impl(Fn&& fn) : fn_(std::forward<Fn>(fn)){}
impl(Fn& fn) : fn_(fn){}
virtual void call()
{
fn_();
}
virtual base* clone() { return new impl<Fn>(fn_); }
};
base* holder_;
function() : holder_(nullptr)
{};
template <typename Fn>
function(Fn&& fn) : holder_(nullptr)
{
holder_ = new impl<Fn>(std::forward<Fn>(fn));
}
function( function&& other)
{
holder_ = other.holder_;
other.holder_ = nullptr;
}
function(const function& other)
{
holder_ = other.holder_->clone();
}
~function()
{
if (holder_) delete holder_;
}
function& operator=(function&& other)
{
if (holder_) delete holder_;
holder_ = other.holder_;
other.holder_ = nullptr;
return *this;
}
function& operator=(const function& other)
{
if (holder_) delete holder_;
holder_ = other.holder_->clone();
return *this;
}
void operator()()
{
holder_->call();
}
};
class Gpio
{
public:
using ExtiHandler = function;
//private:
ExtiHandler handler;
//public:
void enable_irq(ExtiHandler handler_in)
{
// enable interrupt
// ...
// save handler so callback can be issued later
handler = handler_in;
}
};
class Button
{
private:
Gpio& pin;
public:
Button(Gpio& pin_in) : pin(pin_in)
{
};
void button_pressed()
{
std::cout << "Button pressed" << std::endl;
}
void init()
{
pin.enable_irq([this]() { this->button_pressed(); });
}
};
int main() {
Gpio some_pin;
Button b(some_pin);
b.init();
some_pin.handler();
return 0;
}