libev c ++ wrapper function_thunk

lpp*_*ier 8 c++

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);
}
Run Code Online (Sandbox Code Playgroud)

嗨,

我正在使用libev的C++包装器ev ++.ev ++中有这段代码.我知道如何使用API​​,但不完全理解.我可以在事件循环中设置一个Ctrl-C观察器,如下所示:

ev::sig signal_watcher(evloop); 
signal_watcher.set<sigint_cb>(); 
signal_watcher.start(SIGINT); 
Run Code Online (Sandbox Code Playgroud)

其中sigint_cb的函数签名是:

void sigint_cb(ev::sig &w, int revents)
Run Code Online (Sandbox Code Playgroud)

有人可以解释为什么function_thunk可以神奇地将我的sigint_cb函数签名转换为

void (*cb)(EV_P_ ev_watcher *w, int revents)
Run Code Online (Sandbox Code Playgroud)

这是什么C++巫术?谢谢.

小智 5

function_thunk并没有神奇地将sigint_cb签名转换为void (*cb)(EV_P_ ev_watcher *w, int revents)它,只需使用正确的转换参数调用sigint_cb.

从一开始,function_thunk是一个函数模板,可以使用类型的函数指针进行解释void (*)(watcher &w, int).所以基本上当你function_thunk<sigint_cb>在代码中编写某个地方时,编译器会创建相应的function_thunk实例,它看起来像这样:

void function_thunk (EV_P_ ev_watcher *w, int revents)
{
    sigint_cb(*static_cast<watcher *>(w), revents);
}
Run Code Online (Sandbox Code Playgroud)

另请注意,在您的示例中ev::sig,watcher它们是相同的类型,否则function_thunk的模板参数推断/替换将失败.