Generalized Functors - Realizing Command Design Pattern in C++

9,285 views

Published on

This is from my series of lectures on C++ and Design Patterns at Interra. This was first presented in 2008

0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
9,285
On SlideShare
0
From Embeds
0
Number of Embeds
30
Actions
Shares
0
Downloads
118
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide
  • Note that the pad of "checks" used by different diners is not dependent on the menu, and therefore they can support commands to cook many different items.
  • Note that the pad of "checks" used by different diners is not dependent on the menu, and therefore they can support commands to cook many different items.
  • Generalized Functors - Realizing Command Design Pattern in C++

    1. 1. March 06, 2008 Generalized Functors Dr. Partha Pratim Das Interra Systems (India) Pvt. Ltd. Realizing Command Design Pattern in C++
    2. 2. Agenda <ul><li>Design Patterns: Introduction </li></ul><ul><li>Command Design Pattern </li></ul><ul><li>How to realize Command Pattern in C++ </li></ul><ul><ul><li>Function Pointers </li></ul></ul><ul><ul><li>Functor </li></ul></ul><ul><ul><li>Generalized Functors </li></ul></ul>
    3. 3. Design Patterns GoF Basics
    4. 4. What is a Design Pattern? <ul><li>A Design Pattern </li></ul><ul><ul><li>describes a problem that occurs over and over in software engineering </li></ul></ul><ul><ul><li>and then describes the solution in a sufficiently generic manner as to be applicable in a wide variety of contexts. </li></ul></ul>
    5. 5. Essential Elements of a Design Pattern <ul><li>Pattern Name: Descriptor for a design problem, its solutions, and their consequences. </li></ul><ul><li>Problem: Where to apply the pattern and its associated context. </li></ul><ul><li>Solution: Elements that make up the design, their relationships, responsibilities, and collaborations. </li></ul><ul><li>Consequences: Results and trade-offs in applying the pattern. </li></ul>
    6. 6. Sample Design Patterns Command Composite Abstract Factory Iterator Proxy Singleton Visitor Behavioral Structural Creational
    7. 7. Command Design Pattern The World of Delegation
    8. 8. “ Check @ Diner” – A Command Pattern <ul><li>Customer places an Order with Waitress </li></ul><ul><li>Waitress writes Order on check. </li></ul><ul><li>Order is queued to Cook. </li></ul>
    9. 9. “ Compose & Send Mail” – A Command Pattern <ul><li>Sender composes a Mail with Word and presses “Send” </li></ul><ul><li>Mail is queued on Outbox. </li></ul><ul><li>SendMail thread checks the connection and send the Mails from Outbox. </li></ul>
    10. 10. Command Pattern <ul><li>Intent </li></ul><ul><ul><li>Encapsulate requests for service from an object inside other objects to allow manipulation of the requests in various ways </li></ul></ul>
    11. 11. Command Pattern <ul><li>Motivation </li></ul>
    12. 12. Command Pattern <ul><li>Motivation </li></ul>
    13. 13. Command Pattern <ul><li>Applicability </li></ul><ul><ul><li>The Command pattern can be used </li></ul></ul><ul><ul><ul><li>To implement a callback function capability </li></ul></ul></ul><ul><ul><ul><li>To specify, queue, & execute requests at different times </li></ul></ul></ul><ul><ul><ul><li>To support undo and change log operations </li></ul></ul></ul>
    14. 14. Command Pattern <ul><li>Structure </li></ul><ul><li>Interface Separation </li></ul><ul><li>Time Separation </li></ul>
    15. 15. Command Pattern <ul><li>Participants </li></ul><ul><ul><li>Command </li></ul></ul><ul><ul><ul><li>declares an interface for executing an operation. </li></ul></ul></ul><ul><ul><li>ConcreteCommand (PasteCommand, OpenCommand) </li></ul></ul><ul><ul><ul><li>defines a binding between a Receiver object and an action. </li></ul></ul></ul><ul><ul><ul><li>implements Execute by invoking the corresponding operation(s) on Receiver. </li></ul></ul></ul><ul><ul><li>Client (Application) </li></ul></ul><ul><ul><ul><li>creates a ConcreteCommand object and sets its receiver. </li></ul></ul></ul><ul><ul><li>Invoker (MenuItem) </li></ul></ul><ul><ul><ul><li>asks the command to carry out the request. </li></ul></ul></ul><ul><ul><li>Receiver (Document, Application) </li></ul></ul><ul><ul><ul><li>knows how to perform the operations associated with carrying out a request. Any class may serve as a Receiver. </li></ul></ul></ul>
    16. 16. Command Pattern <ul><li>Collaborations </li></ul>
    17. 17. Command Pattern <ul><li>Consequences </li></ul><ul><ul><li>Command decouples the object that invokes the operation from the one that knows how to perform it </li></ul></ul><ul><ul><li>Commands are first-class objects. They can be manipulated and extended like any other object. </li></ul></ul><ul><ul><li>Commands can be made into a composite command </li></ul></ul>
    18. 18. Command Pattern Macro / Composite Command
    19. 19. Command Pattern <ul><li>Implementation Issues </li></ul><ul><ul><li>How intelligent should a command object be? </li></ul></ul><ul><ul><li>Dumb: Delegates the required action to a receiver object </li></ul></ul><ul><ul><li>Smart: Implements everything itself without delegating to a receiver object at all </li></ul></ul><ul><li>Use Functor? </li></ul><ul><ul><li>Active Command: </li></ul></ul><ul><ul><ul><li>A functor object usually implements the desired behavior itself without delegation to another object. </li></ul></ul></ul><ul><ul><li>Forwarding Command: </li></ul></ul><ul><ul><ul><li>A command object frequently delegates the desired behavior to another receiver object. </li></ul></ul></ul>
    20. 20. Command Pattern: Request-in-Object
    21. 21. Sample Command Pattern Usage <ul><li>Multi-level undo / redo  </li></ul><ul><ul><li>The program can keep a pair of stacks of commands. </li></ul></ul><ul><li>Transactional behavior  </li></ul><ul><ul><li>Rollback for all-or-none operations </li></ul></ul><ul><ul><li>Installers / Databases. </li></ul></ul><ul><ul><li>Two-phase commit. </li></ul></ul><ul><li>Progress bars  </li></ul>
    22. 22. Sample Command Pattern Usage <ul><li>Wizards  </li></ul><ul><ul><li>What we see </li></ul></ul><ul><ul><ul><li>Several pages of configuration for a single action. </li></ul></ul></ul><ul><ul><ul><li>Action fires when the user clicks the &quot;Finish&quot; button. </li></ul></ul></ul><ul><ul><li>What we need </li></ul></ul><ul><ul><ul><li>Separate user interface code from application code </li></ul></ul></ul><ul><ul><ul><li>Implement the wizard using a command object. </li></ul></ul></ul><ul><ul><ul><li>The command class contains no user interface code. </li></ul></ul></ul><ul><ul><li>How it works </li></ul></ul><ul><ul><ul><li>Created when the wizard is first displayed. </li></ul></ul></ul><ul><ul><ul><li>Each wizard page stores its GUI changes in the command object. </li></ul></ul></ul><ul><ul><ul><li>&quot;Finish&quot; simply triggers a call to execute(). </li></ul></ul></ul>
    23. 23. Sample Command Pattern Usage
    24. 24. Sample Command Pattern Usage
    25. 25. Sample Command Pattern Usage
    26. 26. Sample Command Pattern Usage
    27. 27. Sample Command Pattern Usage
    28. 28. Sample Command Pattern Usage <ul><li>GUI buttons and menu items  </li></ul><ul><ul><li>In Swing and Borland Delphi programming, an Action is a command object. </li></ul></ul><ul><li>Thread pools / Parallel Processing </li></ul><ul><ul><li>Master/Worker pattern </li></ul></ul><ul><li>Macro recording </li></ul><ul><li>Command across Network  </li></ul><ul><ul><li>Player actions in computer games. </li></ul></ul><ul><li>  Mobile Code  </li></ul><ul><ul><li>Deliver a new behavior to remote locations </li></ul></ul>
    29. 29. How to Implement Command Pattern? <ul><li>Function Pointers? </li></ul><ul><li>Functors? </li></ul><ul><li>Generalized Functors? </li></ul>
    30. 30. Function Pointers Recap
    31. 31. Function Pointers <ul><li>Points to the address of a function </li></ul><ul><ul><li>Ordinary C functions </li></ul></ul><ul><ul><li>Static C++ member functions </li></ul></ul><ul><ul><li>Non-static C++ member functions </li></ul></ul><ul><li>Points to a function with a specific signature </li></ul><ul><ul><li>List of Calling Parameter Types </li></ul></ul><ul><ul><li>Return-Type </li></ul></ul><ul><ul><li>Calling Convention </li></ul></ul>
    32. 32. Function Pointers <ul><li>Operations </li></ul><ul><ul><li>Assign an Address to a Function Pointer </li></ul></ul><ul><ul><li>Compare two Function Pointers </li></ul></ul><ul><ul><li>Call a Function using a Function Pointer </li></ul></ul><ul><ul><li>Pass a Function Pointer as an Argument </li></ul></ul><ul><ul><li>Return a Function Pointer </li></ul></ul><ul><ul><li>Arrays of Function Pointers </li></ul></ul>
    33. 33. Function Pointers <ul><li>Programming Techniques for </li></ul><ul><ul><li>Replacing switch/if-statements, </li></ul></ul><ul><ul><li>Realizing user-defined late-binding or </li></ul></ul><ul><ul><li>Implementing callbacks. </li></ul></ul>
    34. 34. Function Pointers <ul><li>Calculator with operators (+, –, *, /) </li></ul><ul><li>// The four arithmetic operations </li></ul><ul><li>float Plus (float a, float b) { return a+b; } </li></ul><ul><li>float Minus (float a, float b) { return a-b; } </li></ul><ul><li>float Multiply(float a, float b) { return a*b; } </li></ul><ul><li>float Divide (float a, float b) { return a/b; } </li></ul><ul><li>// Solution with a switch-statement </li></ul><ul><li>void Switch(float a, float b, char opCode) { </li></ul><ul><ul><li>float result; </li></ul></ul><ul><ul><li>switch(opCode) { // execute operation </li></ul></ul><ul><ul><ul><li>case ’+’ : result = Plus (a, b); break; </li></ul></ul></ul><ul><ul><ul><li>case ’-’ : result = Minus (a, b); break; </li></ul></ul></ul><ul><ul><ul><li>case ’*’ : result = Multiply (a, b); break; </li></ul></ul></ul><ul><ul><ul><li>case ’/’ : result = Divide (a, b); break; </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><ul><li>cout << &quot;Switch: 2+5=&quot; << result << endl; // display result </li></ul></ul><ul><ul><li>} </li></ul></ul>
    35. 35. Function Pointers – Replace Switch / IF Statements <ul><li>One of the four basic Arithmetic Operations - Addition </li></ul><ul><li>float Plus (float a, float b) { return a+b; } </li></ul><ul><li>void Switch_With_Function_Pointer (float a, float b, </li></ul><ul><ul><li>float (*pt2Func)(float, float)) </li></ul></ul><ul><li>{ </li></ul><ul><ul><li>float result = pt2Func(a, b); </li></ul></ul><ul><ul><li>cout << a << &quot;+&quot; << b << &quot;=&quot; << result << endl; </li></ul></ul><ul><li>} </li></ul><ul><li>void main() </li></ul><ul><li>{ </li></ul><ul><ul><li>Switch_With_Function_Pointer(2, 5, &Plus); </li></ul></ul><ul><li>} </li></ul>
    36. 36. Function Pointers – Late Binding / Virtual Function <ul><li>Late Binding is a C++ Feature </li></ul><ul><li>class A { </li></ul><ul><li>public: </li></ul><ul><ul><li>void f(); </li></ul></ul><ul><ul><li>virtual void g(); </li></ul></ul><ul><li>}; </li></ul><ul><li>class B: public A { </li></ul><ul><li>public: </li></ul><ul><ul><li>void f(); </li></ul></ul><ul><ul><li>virtual void g(); </li></ul></ul><ul><li>}; </li></ul><ul><li>void main() { </li></ul><ul><ul><li>A a; </li></ul></ul><ul><ul><li>B b; </li></ul></ul><ul><ul><li>A *p = &b; </li></ul></ul><ul><ul><li>a.f(); // A::f() </li></ul></ul><ul><ul><li>a.g(); // A::g() </li></ul></ul><ul><ul><li>p->f();// A::f() </li></ul></ul><ul><ul><li>p->g();// B::g() </li></ul></ul><ul><li>} </li></ul>
    37. 37. Function Pointers – Callbacks <ul><li>Quick Sort Implementation using callback in ‘qsort’ </li></ul><ul><li>int CmpFunc(const void* a, const void* b) { </li></ul><ul><ul><li>int ret = (*(const int*)a > *(const int*) b)? 1: </li></ul></ul><ul><ul><ul><li>(*(const int*)a == *(const int*) b)? 0: -1; </li></ul></ul></ul><ul><ul><li>return ret; </li></ul></ul><ul><li>} </li></ul><ul><li>void main() { </li></ul><ul><ul><li>int field[10]; </li></ul></ul><ul><ul><li>for(int c=10;c>0;c--) </li></ul></ul><ul><ul><ul><li>field[10-c]=c; </li></ul></ul></ul><ul><ul><li>qsort((void*) field, 10, sizeof(field[0]), CmpFunc); </li></ul></ul><ul><li>} </li></ul>
    38. 38. Function Pointers <ul><li>Issues </li></ul><ul><ul><li>No value semantics </li></ul></ul><ul><ul><li>Weak type checking </li></ul></ul><ul><ul><li>Two function pointers having identical signature are necessarily indistinguishable </li></ul></ul><ul><ul><li>No encapsulation for parameters </li></ul></ul>
    39. 39. Functors Function Objects in C++
    40. 40. Functors / Closures <ul><li>Smart Functions </li></ul><ul><ul><li>Functors are functions with a state. </li></ul></ul><ul><ul><li>Functors encapsulate C / C++ function pointers </li></ul></ul><ul><ul><ul><li>Uses templates and </li></ul></ul></ul><ul><ul><ul><li>Engages polymorphism. </li></ul></ul></ul><ul><li>Has its own Type </li></ul><ul><ul><li>A class with </li></ul></ul><ul><ul><ul><li>zero or more private members to store the state and </li></ul></ul></ul><ul><ul><ul><li>an overloaded operator() to execute the function. </li></ul></ul></ul><ul><li>Usually faster than ordinary Functions </li></ul><ul><li>Can be used to implement callbacks. </li></ul>
    41. 41. Basic Functor <ul><li>Any class that overloads the function call operator: </li></ul><ul><ul><li>void operator()(); </li></ul></ul><ul><ul><li>int operator()(int, int); </li></ul></ul><ul><ul><li>double operator()(int, double); </li></ul></ul><ul><ul><li>... </li></ul></ul>
    42. 42. Functors: Elementary Example <ul><li>int AdderFunction(int a, int b) { </li></ul><ul><ul><li>return a + b; </li></ul></ul><ul><li>} </li></ul><ul><li>class AdderFunctor { </li></ul><ul><li>public: </li></ul><ul><ul><li>int operator()(int a, int b) { </li></ul></ul><ul><ul><ul><li>return a + b; </li></ul></ul></ul><ul><ul><li>} </li></ul></ul><ul><li>}; </li></ul><ul><li>void main() { </li></ul><ul><ul><li>int x = 5; </li></ul></ul><ul><ul><li>int y = 7; </li></ul></ul><ul><ul><li>int z = AdderFunction(x, y); </li></ul></ul><ul><ul><li>AdderFunctor aF; </li></ul></ul><ul><ul><li>int w = aF(x, y); </li></ul></ul><ul><li>} </li></ul>
    43. 43. Functors: Examples from STL <ul><li>Fill a vector with random numbers </li></ul><ul><ul><li>Function Pointer rand as Function Object </li></ul></ul>vector<int> V(100); generate(V.begin(), V.end(), rand);
    44. 44. Functors: Examples from STL <ul><li>Sort a vector of double by magnitude </li></ul><ul><ul><li>User-defined Functor less_mag </li></ul></ul><ul><li>struct less_mag: public </li></ul><ul><ul><li>binary_function<double, double, bool> { </li></ul></ul><ul><ul><ul><li>bool operator()(double x, double y) </li></ul></ul></ul><ul><ul><ul><li>{ return fabs(x) < fabs(y); } </li></ul></ul></ul><ul><li>}; </li></ul><ul><li>vector<double> V; ... </li></ul><ul><li>sort(V.begin(), V.end(), less_mag()); </li></ul>
    45. 45. Functors: Examples from STL <ul><li>Find the sum of elements in a vector </li></ul><ul><ul><li>User-defined Functor adder with local state </li></ul></ul><ul><li>struct adder: public </li></ul><ul><ul><li>unary_function<double, void> { </li></ul></ul><ul><ul><li>adder() : sum(0) {} </li></ul></ul><ul><ul><li>double sum; </li></ul></ul><ul><ul><li>void operator()(double x) { sum += x; } </li></ul></ul><ul><li>}; </li></ul><ul><li>vector<double> V; </li></ul><ul><li>... </li></ul><ul><li>adder result = </li></ul><ul><ul><li>for_each(V.begin(), V.end(), adder()); </li></ul></ul><ul><li>cout << &quot;The sum is &quot; << result.sum << endl; </li></ul>
    46. 46. Generalized Functors Basic Notions
    47. 47. Generalized Functors <ul><li>Encapsulates any processing invocation </li></ul><ul><li>Accepts </li></ul><ul><ul><li>pointers to simple functions, </li></ul></ul><ul><ul><li>pointers to member functions, </li></ul></ul><ul><ul><li>functors, and </li></ul></ul><ul><ul><li>other generalized functors –with some or all of their respective arguments. </li></ul></ul><ul><li>Is typesafe </li></ul><ul><ul><li>Never matches the wrong argument types to the wrong functions. </li></ul></ul><ul><li>Is an object with value semantics </li></ul><ul><ul><li>Fully supports </li></ul></ul><ul><ul><ul><li>copying, </li></ul></ul></ul><ul><ul><ul><li>assignment, and </li></ul></ul></ul><ul><ul><ul><li>pass by value. </li></ul></ul></ul><ul><li>A generalized functor can be copied freely and does not expose virtual member functions. </li></ul>
    48. 48. Generalized Functors <ul><li>Implementation </li></ul><ul><ul><li>Handle-Body (PIMPL) Idiom </li></ul></ul>class Functor { public: void operator()(); // other member functions private: // implementation goes here FunctorImpl *pImpl_; };
    49. 49. Generalized Functors <ul><li>Parameterized Return Values </li></ul><ul><li>template <typename ResultType> </li></ul><ul><li>class Functor { </li></ul><ul><li>public: </li></ul><ul><ul><li>ResultType operator()(); </li></ul></ul><ul><ul><li>// other member functions </li></ul></ul><ul><li>private: </li></ul><ul><ul><li>// implementation </li></ul></ul><ul><li>}; </li></ul>
    50. 50. Generalized Functors <ul><li>No Argument (Generator) </li></ul><ul><li>One Argument (Unary Function) </li></ul><ul><li>Two Arguments (Binary Function) </li></ul>template <typename ResultType> class Functor { ... }; template <typename ResultType, typename Parm1> class Functor { ... }; template <typename ResultType, typename Parm1, typename Parm2> class Functor { ... };
    51. 51. Generalized Functors <ul><li>Variable List of Parameters </li></ul><ul><ul><li>Variadic Function ellipses not allowed for templates </li></ul></ul><ul><li>Needs a set of Helper Templates </li></ul><ul><li>Needs representation for Collection of Types </li></ul>int VarArgIntSum(int nParam, ...) { va_list va; va_start(va, nParam); for(int i = 0 , sum = 0 ; i < nParam; i++) { int& val = va_arg(va, int); sum += val; } va_end(va); return sum; }
    52. 52. Helper Templates <ul><li>NullType </li></ul><ul><ul><li>class NullType {}; </li></ul></ul><ul><ul><li>N ot an interesting type. </li></ul></ul><ul><ul><li>M ark s the end of a typelist and to return &quot;type not found&quot; information. </li></ul></ul><ul><li>EmptyType </li></ul><ul><ul><li>struct EmptyType {}; </li></ul></ul><ul><ul><li>&quot;don't care&quot; type for a template. </li></ul></ul><ul><ul><li>Legal to inherit from </li></ul></ul>
    53. 53. Typelist <ul><li>Typelists are a C++ tool for manipulating collections (list) of types. </li></ul><ul><li>Typelist holds two types a ccessible through the inner names. </li></ul><ul><ul><li>Head </li></ul></ul><ul><ul><li>Tail </li></ul></ul>
    54. 54. Typelist <ul><li>Examples </li></ul><ul><li>Generic List </li></ul>template <class T, class U> struct Typelist { typedef T Head; typedef U Tail; }; typedef Typelist<char, Typelist<signed char, unsigned char> > CharList; typedef Typelist<char, Typelist<signed char, Typelist<unsigned char, NullType> > > AllCharTypes;
    55. 55. Typelist: Compute Length <ul><li>Recursion Exit </li></ul><ul><li>Recursion Descend Instantiation </li></ul>template <class T, class U> struct Length< Typelist<T, U> > { enum { value = 1 + Length<U>::value }; }; template <class TList> struct Length; template <> struct Length<NullType> { enum { value = 0 }; };
    56. 56. Typelist: Index a Type <ul><li>Generic Template </li></ul><ul><li>Recursion Exit </li></ul><ul><li>Recursion Descend Instantiation </li></ul>template <class Head, class Tail, unsigned int i> struct TypeAt<Typelist<Head, Tail>, i> { typedef typename TypeAt<Tail, i - 1>::Result Result; }; template <class Head, class Tail> struct TypeAt<Typelist<Head, Tail>, 0> { typedef Head Result; }; template <class Head, class Tail> struct TypeAt;
    57. 57. Typelist: Arbitrary Number of Types <ul><li>Iterative Macro Definition </li></ul>#define TYPELIST_1(T1) Typelist<T1, NullType> #define TYPELIST_2(T1, T2) Typelist<T1, TYPELIST_1(T2) > #define TYPELIST_3(T1, T2, T3) Typelist<T1, TYPELIST_2(T2, T3) > #define TYPELIST_4(T1, T2, T3, T4) Typelist<T1, TYPELIST_3(T2, T3, T4) > //... //#define TYPELIST_50(...) ...
    58. 58. Functor Implementation <ul><li>template <typename R, class TList> </li></ul><ul><li>class FunctorImpl; </li></ul><ul><li>template <typename R> </li></ul><ul><li>class FunctorImpl<R, NullType> { </li></ul><ul><li>public: </li></ul><ul><ul><li>virtual R operator()() = 0; </li></ul></ul><ul><ul><li>virtual FunctorImpl* Clone() const = 0; </li></ul></ul><ul><ul><li>virtual ~FunctorImpl() {} </li></ul></ul><ul><li>}; </li></ul>
    59. 59. Functor Implementation <ul><li>template <typename R, typename P1> </li></ul><ul><li>class FunctorImpl<R, TYPELIST_1(P1)> { </li></ul><ul><li>public: </li></ul><ul><ul><li>virtual R operator()(P1) = 0; </li></ul></ul><ul><ul><li>virtual FunctorImpl* Clone() const = 0; </li></ul></ul><ul><ul><li>virtual ~FunctorImpl() {} </li></ul></ul><ul><li>}; </li></ul><ul><li>template <typename R, typename P1, typename P2> </li></ul><ul><li>class FunctorImpl<R, TYPELIST_2(P1, P2)> { </li></ul><ul><li>public: </li></ul><ul><ul><li>virtual R operator()(P1, P2) = 0; </li></ul></ul><ul><ul><li>virtual FunctorImpl* Clone() const = 0; </li></ul></ul><ul><ul><li>virtual ~FunctorImpl() {} </li></ul></ul><ul><li>}; </li></ul>
    60. 60. The Functor <ul><li>template <typename R, class TList> </li></ul><ul><li>class Functor { </li></ul><ul><li>public: </li></ul><ul><ul><li>Functor(); </li></ul></ul><ul><ul><li>Functor(const Functor&); </li></ul></ul><ul><ul><li>Functor& operator=(const Functor&); </li></ul></ul><ul><ul><li>explicit Functor(std::auto_ptr<Impl> spImpl); </li></ul></ul><ul><li>... </li></ul><ul><li>private: </li></ul><ul><ul><li>// Handy type definition for the body type </li></ul></ul><ul><ul><li>typedef FunctorImpl<R, TList> Impl; </li></ul></ul><ul><ul><li>std::auto_ptr<Impl> spImpl_; </li></ul></ul><ul><li>}; </li></ul>
    61. 61. The Functor: Forwarding Operator <ul><li>template <typename R, class TList> </li></ul><ul><li>class Functor { </li></ul><ul><li>... as above ... </li></ul><ul><li>typedef TList ParmList; </li></ul><ul><li>typedef typename </li></ul><ul><ul><li>TypeAt<TList, 0, EmptyType>::Result Parm1; </li></ul></ul><ul><li>typedef typename </li></ul><ul><ul><li>TypeAt<TList, 1, EmptyType>::Result Parm2; </li></ul></ul><ul><li>public: </li></ul><ul><ul><li>R operator()() </li></ul></ul><ul><ul><ul><li>{ return (*spImpl_)(); } </li></ul></ul></ul><ul><ul><li>R operator()(Parm1 p1) </li></ul></ul><ul><ul><ul><li>{ return (*spImpl_)(p1); } </li></ul></ul></ul><ul><ul><li>R operator()(Parm1 p1, Parm2 p2) </li></ul></ul><ul><ul><ul><li>{ return (*spImpl_)(p1, p2); } </li></ul></ul></ul><ul><li>}; </li></ul>
    62. 62. Using Functor // Define a Functor that accepts an int and // a double and returns a double. Functor<double, TYPELIST_2(int, double)> myFunctor; // Invoke it. operator()(double, int) is generated. double result = myFunctor(4, 5.6); // Wrong invocation. double result = myFunctor(); // error! // operator()() is invalid because // FunctorImpl<double, TYPELIST_2(int, double)> // does not define one.
    63. 63. Using Functor <ul><li>Work by yourself </li></ul>
    64. 64. References <ul><li>Chapter 5: Generalized Functors in Modern C++ Design: Generic Programming and Design Patterns Applied </li></ul><ul><ul><li>Andrei Alexandrescu </li></ul></ul><ul><li>Chapter 22. Function Objects and Callbacks in C++ Templates: The Complete Guide </li></ul><ul><ul><li>David Vandevoorde & Nicolai M. Josuttis </li></ul></ul><ul><li>Chapter 8. STL Function Objects in The C++ Standard Library: A Tutorial and Reference </li></ul><ul><ul><li>Nicolai M. Josuttis </li></ul></ul><ul><li>Effective C++ & More Effective C++ </li></ul><ul><ul><li>Scott Meyers </li></ul></ul>
    65. 65. Thank You

    ×