Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>The most efficient way is to <code>voidify</code> the lambda directly.</p> <pre><code>#include &lt;iostream&gt; #include &lt;tuple&gt; #include &lt;memory&gt; template&lt;typename... Args, typename Lambda&gt; std::pair&lt; void(*)(void*, Args...), std::unique_ptr&lt;void, void(*)(void*)&gt; &gt; voidify( Lambda&amp;&amp; l ) { typedef typename std::decay&lt;Lambda&gt;::type Func; std::unique_ptr&lt;void, void(*)(void*)&gt; data( new Func(std::forward&lt;Lambda&gt;(l)), +[](void* ptr){ delete (Func*)ptr; } ); return { +[](void* v, Args... args)-&gt;void { Func* f = static_cast&lt; Func* &gt;(v); (*f)(std::forward&lt;Args&gt;(args)...); }, std::move(data) }; } void register_callback( void(*function)(void*), void * p ) { function(p); // to test } void test() { int x = 0; auto closure = [&amp;]()-&gt;void { ++x; }; auto voidified = voidify(closure); register_callback( voidified.first, voidified.second.get() ); register_callback( voidified.first, voidified.second.get() ); std::cout &lt;&lt; x &lt;&lt; "\n"; } int main() { test(); } </code></pre> <p>here <code>voidify</code> takes a lambda and (optionally) a list of arguments, and generates a traditional C-style callback-<code>void*</code> pair. The <code>void*</code> is owned by a <code>unique_ptr</code> with a special deleter so its resources are properly cleaned up.</p> <p>The advantage of this over a <code>std::function</code> solution is efficiency -- I eliminated one level of run-time indirection. The lifetime that the callback is valid is also clear, in that it is in the <code>std::unique_ptr&lt;void, void(*)(void*)&gt;</code> returned by <code>voidify</code>.</p> <p><code>unique_ptr&lt;T,D&gt;</code>s can be <code>move</code>d into <code>shared_ptr&lt;T&gt;</code> if you want a more complex lifetime.</p> <hr> <p>The above mixes lifetime with data, and type erasure with utility. We can split it:</p> <pre><code>template&lt;typename... Args, typename Lambda&gt; std::pair&lt; void(*)(void*, Args...), std::decay_t&lt;Lambda&gt; &gt; voidify( Lambda&amp;&amp; l ) { typedef typename std::decay&lt;Lambda&gt;::type Func; return { +[](void* v, Args... args)-&gt;void { Func* f = static_cast&lt; Func* &gt;(v); (*f)(std::forward&lt;Args&gt;(args)...); }, std::forward&lt;Lambda&gt;(l) }; } </code></pre> <p>Now <code>voidify</code> does not allocate. Simply store your voidify for the lifetime of the callback, passing a pointer-to-<code>second</code> as your <code>void*</code> along side the <code>first</code> function pointer.</p> <p>If you need to store this construct off the stack, converting the lambda to a <code>std::function</code> may help. Or use the first variant above.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload