Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I wanted to follow off of @Insilico's answer with a bit of my own stuff.</p> <p>Before I had stumbled upon this answer, I was trying to figure out fast callbacks as well that incurred no overhead and were uniquely comparable / identified by function signature only. What I ended up creating - with some serious help from <a href="http://chat.stackoverflow.com/rooms/10/loungec">Klingons Who Happened To Be at a BBQ</a> - works for all function types (except Lambdas, unless you store the Lambda, but don't try it because it's <a href="http://chat.stackoverflow.com/transcript/10?m=6385687#6385687">really difficult and hard to do and may result in a robot proving to you how difficult it is and making you eat the shit for it</a>). Thanks to @sehe, @nixeagle, @StackedCrooked, @CatPlusPlus, @Xeo, @DeadMG and of course @Insilico for the help in creating the event system. Feel free to use as you desire.</p> <p>Anyway, an example is up on ideone, but the source code is also here for your use (because, since Liveworkspace went down, I don't trust them shady compiling services. Who knows when ideone will go down?!). I hope this is useful for somebody who's not busy Lambda/Function-objecting the world to pieces:</p> <p>IMPORTANT NOTE: As of right now (28/11/2012, 9:35 PM) This variadic version will not work with the Microsoft VC++ 2012 November CTP (Milan). If you want to use it with that, you will have to get rid of all the variadic stuff and explicitly enumerate the number of arguments (and possibly template-specialize the 1-argument type for <code>Event</code> for <code>void</code>) to make it work. It's a pain, and I could only manage to write it out for 4 arguments before I got tired (and decided that passing more than 4 arguments was a bit of a stretch).</p> <p><a href="http://ideone.com/PTH7aQ" rel="noreferrer">Source Example</a></p> <p>Source:</p> <pre><code>#include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;utility&gt; #include &lt;algorithm&gt; template&lt;typename TFuncSignature&gt; class Callback; template&lt;typename R, typename... Args&gt; class Callback&lt;R(Args...)&gt; { public: typedef R(*TFunc)(void*, Args...); Callback() : obj(0), func(0) {} Callback(void* o, TFunc f) : obj(o), func(f) {} R operator()(Args... a) const { return (*func)(obj, std::forward&lt;Args&gt;(a)...); } typedef void* Callback::*SafeBoolType; operator SafeBoolType() const { return func? &amp;Callback::obj : 0; } bool operator!() const { return func == 0; } bool operator== (const Callback&lt;R (Args...)&gt;&amp; right) const { return obj == right.obj &amp;&amp; func == right.func; } bool operator!= (const Callback&lt;R (Args...)&gt;&amp; right) const { return obj != right.obj || func != right.func; } private: void* obj; TFunc func; }; namespace detail { template&lt;typename R, class T, typename... Args&gt; struct DeduceConstMemCallback { template&lt;R(T::*Func)(Args...) const&gt; inline static Callback&lt;R(Args...)&gt; Bind(T* o) { struct _ { static R wrapper(void* o, Args... a) { return (static_cast&lt;T*&gt;(o)-&gt;*Func)(std::forward&lt;Args&gt;(a)...); } }; return Callback&lt;R(Args...)&gt;(o, (R(*)(void*, Args...)) _::wrapper); } }; template&lt;typename R, class T, typename... Args&gt; struct DeduceMemCallback { template&lt;R(T::*Func)(Args...)&gt; inline static Callback&lt;R(Args...)&gt; Bind(T* o) { struct _ { static R wrapper(void* o, Args... a) { return (static_cast&lt;T*&gt;(o)-&gt;*Func)(std::forward&lt;Args&gt;(a)...); } }; return Callback&lt;R(Args...)&gt;(o, (R(*)(void*, Args...)) _::wrapper); } }; template&lt;typename R, typename... Args&gt; struct DeduceStaticCallback { template&lt;R(*Func)(Args...)&gt; inline static Callback&lt;R(Args...)&gt; Bind() { struct _ { static R wrapper(void*, Args... a) { return (*Func)(std::forward&lt;Args&gt;(a)...); } }; return Callback&lt;R(Args...)&gt;(0, (R(*)(void*, Args...)) _::wrapper); } }; } template&lt;typename R, class T, typename... Args&gt; detail::DeduceConstMemCallback&lt;R, T, Args...&gt; DeduceCallback(R(T::*)(Args...) const) { return detail::DeduceConstMemCallback&lt;R, T, Args...&gt;(); } template&lt;typename R, class T, typename... Args&gt; detail::DeduceMemCallback&lt;R, T, Args...&gt; DeduceCallback(R(T::*)(Args...)) { return detail::DeduceMemCallback&lt;R, T, Args...&gt;(); } template&lt;typename R, typename... Args&gt; detail::DeduceStaticCallback&lt;R, Args...&gt; DeduceCallback(R(*)(Args...)) { return detail::DeduceStaticCallback&lt;R, Args...&gt;(); } template &lt;typename... T1&gt; class Event { public: typedef void(*TSignature)(T1...); typedef Callback&lt;void(T1...)&gt; TCallback; typedef std::vector&lt;TCallback&gt; InvocationTable; protected: InvocationTable invocations; public: const static int ExpectedFunctorCount = 2; Event() : invocations() { invocations.reserve(ExpectedFunctorCount); } template &lt;void (* TFunc)(T1...)&gt; void Add() { TCallback c = DeduceCallback(TFunc).template Bind&lt;TFunc&gt;(); invocations.push_back(c); } template &lt;typename T, void (T::* TFunc)(T1...)&gt; void Add(T&amp; object) { Add&lt;T, TFunc&gt;(&amp;object); } template &lt;typename T, void (T::* TFunc)(T1...)&gt; void Add(T* object) { TCallback c = DeduceCallback(TFunc).template Bind&lt;TFunc&gt;(object); invocations.push_back(c); } template &lt;typename T, void (T::* TFunc)(T1...) const&gt; void Add(T&amp; object) { Add&lt;T, TFunc&gt;(&amp;object); } template &lt;typename T, void (T::* TFunc)(T1...) const&gt; void Add(T* object) { TCallback c = DeduceCallback(TFunc).template Bind&lt;TFunc&gt;(object); invocations.push_back(c); } void Invoke(T1... t1) { for(size_t i = 0; i &lt; invocations.size() ; ++i) invocations[i](std::forward&lt;T1&gt;(t1)...); } void operator()(T1... t1) { Invoke(std::forward&lt;T1&gt;(t1)...); } size_t InvocationCount() { return invocations.size(); } template &lt;void (* TFunc)(T1...)&gt; bool Remove () { return Remove (DeduceCallback(TFunc).template Bind&lt;TFunc&gt;()); } template &lt;typename T, void (T::* TFunc)(T1...)&gt; bool Remove (T&amp; object) { return Remove &lt;T, TFunc&gt;(&amp;object); } template &lt;typename T, void (T::* TFunc)(T1...)&gt; bool Remove (T* object) { return Remove (DeduceCallback(TFunc).template Bind&lt;TFunc&gt;(object)); } template &lt;typename T, void (T::* TFunc)(T1...) const&gt; bool Remove (T&amp; object) { return Remove &lt;T, TFunc&gt;(&amp;object); } template &lt;typename T, void (T::* TFunc)(T1...) const&gt; bool Remove (T* object) { return Remove (DeduceCallback(TFunc).template Bind&lt;TFunc&gt;(object)); } protected: bool Remove( TCallback const&amp; target ) { auto it = std::find(invocations.begin(), invocations.end(), target); if (it == invocations.end()) return false; invocations.erase(it); return true; } }; </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

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