homer512

Template visitor

Jan 24th, 2014
219
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <utility>
  5.  
  6. using namespace std;
  7.  
  8. struct Base;
  9. struct A;
  10. struct B;
  11.  
  12. struct Visitor {
  13.   virtual void visit (Base& b) = 0;
  14.   virtual void visit (A& a) = 0;
  15.   virtual void visit (B& b) = 0;
  16. };
  17.  
  18. struct Base {
  19.   int av;
  20.   virtual void accept (Visitor& v) { v.visit (*this); }
  21.   template <class VisitorType, class... Params>
  22.   VisitorType accept (Params... args)
  23.   {
  24.     VisitorType v (forward <Params> (args)...);
  25.     this->accept (v);
  26.     return v;
  27.   }
  28.  
  29.   Base () { av = 1;}
  30. };
  31.  
  32. struct A : public Base {
  33.   int bv;
  34.  
  35.   void accept (Visitor& v) { v.visit (*this); }
  36.  
  37.   A () { av = 2; bv = 3; }
  38. };
  39.  
  40. struct B : public Base {
  41.   string cv;
  42.  
  43.   void accept (Visitor& v) { v.visit (*this); }
  44.  
  45.   B () { av = 4; cv = "s5"; }
  46. };
  47.  
  48. struct Print : Visitor {
  49.   void visit (Base& b) { cout << "av " << b.av << endl; }
  50.   void visit (A& b) { cout << "bv " << b.bv << endl; }
  51.   void visit (B& b) { cout << "cv " << b.cv << endl; }
  52. };
  53.  
  54. struct Add : Visitor {
  55.   int av, bv;
  56.   Add (int av, int bv)
  57.     : av (av), bv (bv)
  58.   {}
  59.   void visit (Base& b) { av += b.av; }
  60.   void visit (A& b) { av += b.av; bv += b.bv; }
  61.   void visit (B& b) { av += b.av; }
  62. };
  63.  
  64. struct data {
  65.   vector <Base*> basev;
  66.  
  67.   Base* findb (int value) {
  68.     static Base base; Base* pBase = &base;
  69.    
  70.     for (int i = 0; i < basev.size (); ++i) {
  71.       if (basev[i]->av == value) return basev[i];
  72.     }
  73.     return pBase;
  74.   }
  75. } d;
  76.  
  77.  
  78. int main() {
  79.  
  80.   d.basev.push_back (new Base);
  81.   d.basev.push_back (new A);
  82.   d.basev.push_back (new B);
  83.  
  84.   Base* found = d.findb (4);
  85.  
  86.   found->accept <Print> ();
  87.   int av = found->accept <Add> (0, 0).av;
  88.  
  89.   cout << av << "\n" << "\nDone\n";
  90. }
Advertisement
Add Comment
Please, Sign In to add comment