easy c++ delegates _ ming-lun _allen_ chou

Upload: marius-myburg

Post on 14-Apr-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/29/2019 Easy C++ Delegates _ Ming-Lun _Allen_ Chou

    1/5

    8/12/13 Easy C++ Delegates | Ming-Lun "Allen" Chou

    allenchou.net/2012/04/easy-c-delegates/ 1/5

    Easy C++ DelegatesPosted on April 24, 2012 by Allen Chou

    As I mentioned in myprevious post, I was working on delegates for C++.

    The first article I read was recommended by one of my programming TAs. The authors main concern was

    portability and performance, so he special-cased extensively throughout his code, in order to make sure the

    code works perfectly fine across multiple compilers while still yielding optimal performance. This resulted in

    very verbose and convoluted code. I was half way through comprehending all his code and gave up. The article

    itself, however, is certainly worth reading; it covers in details the difference between function pointers and

    member pointers and points out why they are not easy (also not too hard) to deal with correctly.

    The second post I read was a follow-up to the first one. The code is easier to read; however, the author used

    macros extensively to avoid code duplication in his source files, so trying to untangle the macros in mind while

    reading the code is not a light task. Fortunately, the author provided a clean and untangled example in the

    post, which is just enough to understand the logic behind it.

    I found the last article by Googling C++ delegates. It is the easiest of the three (in terms of sample code),

    since the authors first concern was simplicity instead of performance, and it was just what I needed. He used

    polymorphism to handle function pointers and member function pointers differently. His sample code helped

    me the most in coming up with my own delegate class design. I didnt read through the entire article, though,

    because it was kind of hard for me to read.

    As mentioned before, I started my research on delegates because I wanted to implement a robust event/signal

    system for my next school game project at DigiPen. Thus, one of my concerns was to make the code as simple

    as possible, so that it would be easy for me to explain how it works to my teammates.

    Here Im going to show you what Ive come up with. In order to make things simple, I am going to show you

    simplified version of the delegate class, where it can only point to a function with one parameter. It can be

    easily generalized with templates to deal with any number of parameters once you understand it.

    The Callback Class

    The responsibility of the Callback is to provide an interface for a delegate to invoke the underlying function, be it

    a regular function (static function) or a member function associated with a pointer that holds the object

    address to be used as the value of the this pointer.

    The Ret type is the return type of the function, and the Param0 type is the type of the one parameter passed to the

    function. We are going to extend this class and create two subclasses, one is responsible for static function

    callbacks, and one responsible for member function callbacks.

    Ming-Lun "Allen" ChouMingLun.Cho [email protected]

    1 template 2 class Callback3 {4 public:5 virtual Ret invoke(Param0 param0) = 0;6 };

    http://allenchou.net/2012/04/easy-c-delegates/http://allenchou.net/author/cjcat2266/http://allenchou.net/http://www.digipen.edu/http://www.codeguru.com/cpp/cpp/cpp_mfc/pointers/article.php/c4135/DELEGATES-and-C.htmhttp://www.codeproject.com/Articles/11015/The-Impossibly-Fast-C-Delegateshttp://www.codeproject.com/Articles/7150/Member-Function-Pointers-and-the-Fastest-Possiblehttp://allenchou.net/2012/04/function-pointers-vs-member-function-pointers/http://allenchou.net/author/cjcat2266/http://allenchou.net/2012/04/easy-c-delegates/
  • 7/29/2019 Easy C++ Delegates _ Ming-Lun _Allen_ Chou

    2/5

    8/12/13 Easy C++ Delegates | Ming-Lun "Allen" Chou

    allenchou.net/2012/04/easy-c-delegates/ 2/5

    The StaticFucntionCallback Class

    Static function callbacks are easy to implement, where all you have to do is declare an appropriate function

    pointer, and invoke it using the function pointer invocation syntax.

    The MethodCallback Class

    Member function (method) callbacks require just a little more work, where we have to keep track of which

    object address to use for the this pointer while invoking the method.

    Note that I used the template type Method to handle all possible member function types. It is not type-safe; I

    could have used some non-type template parameter like Ret (T::*method)(Param0) and take extra care of it, just as in

    the aforementioned articles. However, my goal here is to make things simple, so I just use a regular type

    parameter.

    The Delegate Class

    Finally, were going to wrap Callback objects into the Delegate class. The constructor is overloaded to handle both

    cases: static functions and member functions. The corresponding Callback object is created, and the function

    invocation operator would call the correct version of the invoke method through polymorphism.

    1 template 2 class StaticFunctionCallback : public Callback3 {4 private:5 Ret (*func_)(Param0);6 7 public:8 StaticFunctionCallback(Ret (*func)(Param0))9 : func_(func)10 {}11 12 virtual Ret invoke(Param0 param0)13 {14 return (*func_)(param0);15 }16 };

    1 template 2 class MethodCallback : public Callback3 {4 private:5 void *object_;6 Method method_;7 8 public:9 MethodCallback(void *object, Method method)10 : object_(object)11 , method_(method)12 {}13 14 virtual Ret invoke(Param0 param0)15 {16 T *obj = static_cast(object_);17 return (obj->*method_)(param0);18 }19 };

    1 template 2 class Delegate3 {4 private:

  • 7/29/2019 Easy C++ Delegates _ Ming-Lun _Allen_ Chou

    3/5

    8/12/13 Easy C++ Delegates | Ming-Lun "Allen" Chou

    allenchou.net/2012/04/easy-c-delegates/ 3/5

    Some Sample Client Code

    Were pretty much done here. Now Ill just show you how you would use this delegate class in the client code.

    First, I declare four classes with single inheritance and multiple inheritance (just to show that this works in

    both cases), as well as a static function foo.

    Finally, in the main function, four delegates are created to demonstrate different scenarios. Ive tested it with

    GNU g++ compiler and Microsoft Visual Studio C++ Compiler 2008 and it worked perfectly.

    5 Callback *callback_;6 7 public:8 Delegate(Ret (*func)(Param0))9 :callback_(new StaticFunctionCallback(func))

    10 {}11 12 template 13 Delegate(T *object, Method method)14 :callback_(new MethodCallback(object, method))

    15 {}16 17 ~Delegate(void) { delete callback_; }18 19 Ret operator()(Param0 param0)20 {21 return callback_->invoke(param0);22 }23 };

    1 class A2 {3 public:4 5 virtualint foo(int p)6 {7 std::cout

  • 7/29/2019 Easy C++ Delegates _ Ming-Lun _Allen_ Chou

    4/5

    8/12/13 Easy C++ Delegates | Ming-Lun "Allen" Chou

    allenchou.net/2012/04/easy-c-delegates/ 4/5

    About Allen Chou

    Engine Dev / Graphics Programmer / Technical Artist

    View all posts by Allen Chou

    This entry was posted in C /C++, Design Patterns, Programming . Bookmark the permalink.

    3 Responses to Easy C++ Delegates

    1 int main(void)2 {3 A *a = new A();4 A *b = new B();5 A *d = new D();6 7 //static function8 Delegate d1(foo);9 10 //member function

    11 Delegate d2(a, &A::foo);12 13 //member function + subclass instance14 Delegate d3(b, &A::foo);15 16 //member function + subclass instance + multiple inheritance17 Delegate d4(d, &A::foo);18 19 20 d1(100); //"foo(100)"21 d2(200); //"A::foo(200)"22 d3(300); //"B::foo(300)"23 d4(400); //"D::foo(400)"24

    25 return 0;26 }

    Nisnorsays:

    March 23, 2013 at 11:16 am

    Really helpfull article It combines several great sources and one custom delegate implementation. Thank you so much

    Reply

    Charles Hendensays:

    July 22, 2012 at 10:54 pm

    Awesome work, this article really helped me get over a hurdle with neat ev ent handling for my educational game engine.

    Professionally everyone usually uses Dons fastdelegate which is great but unreadable.

    One modification I performed to the code you supplied was implementing a default no argument constructor to the Delegate

    and then splitting out the ex isting ctor to an AddCallback(T *object, Method method) public function to set up the delegate for

    use.

    Then I reference count the callback_ member so one delegate can register many member functions for subscriber type usage.

    Reply

    Jason Wongsays:

    June 26, 2012 at 5:29 am

    Hi, I find your blog by searching c++ delete on google.

    http://allenchou.net/2012/04/easy-c-delegates/#comment-6112http://allenchou.net/2012/04/easy-c-delegates/?replytocom=6269#respondhttp://allenchou.net/2012/04/easy-c-delegates/#comment-6269http://charles.henden.com.au/http://allenchou.net/2012/04/easy-c-delegates/?replytocom=8109#respondhttp://allenchou.net/2012/04/easy-c-delegates/#comment-8109http://allenchou.net/2012/04/easy-c-delegates/http://allenchou.net/category/programming/http://allenchou.net/category/design-patterns/http://allenchou.net/category/programming/cc/http://allenchou.net/author/cjcat2266/
  • 7/29/2019 Easy C++ Delegates _ Ming-Lun _Allen_ Chou

    5/5

    8/12/13 Easy C++ Delegates | Ming-Lun "Allen" Chou

    allenchou.net/2012/04/easy-c-delegates/ 5/5

    Ming-Lun "Allen" Chou

    After reading the articles you mentioned and your code, I write the following implementation for my c++ callback.

    class NullClass;

    template class functor

    {

    private:

    typedef R (*functor_fp_0)();

    typedef R (NullClass::*memFun_0)();

    public:

    functor() { }

    ~functor() { }

    functor(functor_fp_0 a)

    {

    memcpy((void *) &m_fp, (void *) &a, sizeof(functor_fp_0));

    }

    template functor(R (Y::*a)())

    {

    memcpy((void *) &m_memFun, (void *) &a, sizeof(memFun_0));

    }

    void operator = (functor_fp_0 a) {

    memcpy((void *) &m_fp, (void *) &a, sizeof(functor_fp_0));

    }

    template void operator = (R (Y::*a)())

    {

    memcpy((void *) &m_memFun, (void *) &a, sizeof(memFun_0));

    }

    R operator () () {

    return (m_fp)();

    }

    template R operator () (X *x) {return (((NullClass *) x)->*(m_memFun))();

    }

    private:

    functor_fp_0 m_fp;

    memFun_0 m_memFun;

    };

    Reply

    roudly pow ered by WordPress.

    http://wordpress.org/http://allenchou.net/2012/04/easy-c-delegates/?replytocom=6112#respondhttp://allenchou.net/