void set_ (const void *data, void (*cb)(EV_P_ ev_watcher *w, int revents)) throw ()
{
this->data = (void *)data;
ev_set_cb (static_cast<ev_watcher *>(this), cb);
}
// function callback
template<void (*function)(watcher &w, int)>
void set (void *data = 0) throw ()
{
set_ (data, function_thunk<function>);
}
template<void (*function)(watcher &w, int)>
static void function_thunk (EV_P_ ev_watcher *w, int revents)
{
function
(*static_cast<watcher *>(w), revents);
}
Hi,
I'm using libev's C++ wrapper ev++.h. There is this piece of code in ev++.h that I know how to use as an API, but don't fully understand. I can set up a Ctrl-C watcher in the event loop as follows:
ev::sig signal_watcher(evloop);
signal_watcher.set<sigint_cb>();
signal_watcher.start(SIGINT);
where sigint_cb's function signature is :
void sigint_cb(ev::sig &w, int revents)
Can someone explain why function_thunk can magically cast my sigint_cb function signature to
void (*cb)(EV_P_ ev_watcher *w, int revents)
What C++ sorcery is this? Thanks.
function_thunk doesn't magically cast sigint_cb signature to void (*cb)(EV_P_ ev_watcher *w, int revents)
it just call sigint_cb with properly casted arguments.
From the beginning, function_thunk is a function template which can be intstantiated with function pointer of type void (*)(watcher &w, int)
.
So basically when you will write function_thunk<sigint_cb>
somewhere in your code, compiler will create corresponding function_thunk instance which will be looking like this:
void function_thunk (EV_P_ ev_watcher *w, int revents)
{
sigint_cb(*static_cast<watcher *>(w), revents);
}
Also note that in you example ev::sig
and watcher
are the same types, otherwise template argument deduction/substitution for function_thunk would failed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With