паттерн посетитель (Visitor)
От: Abyx Россия  
Дата: 06.06.11 19:35
Оценка: :))
Понадобилось реализовать паттерн Visitor, и что-то не получается придумать как сделать так чтоб было и просто и удобно и эффективно %)
(GoF читал, Александреску читал, сам думал )

Значится есть иерархия классов
struct visitor;

struct node
{
   virtual void accept(visitor* v) = 0;
};

struct some : node
{
   virtual void accept(visitor* v);
};

struct other : node
{
   virtual void accept(visitor* v);
};


и хочется делать таких посетителей, чтоб без кучи перегрузок виртуальных методов, например как в boost.variant
struct test_visitor
{
   void operator()(some&) { std::cout << "some visited\n"; }
   void operator()(other&) { std::cout << "other visited\n"; }
   template<class T> void operator()(T&) { std::cout << "i-dunno-what visited\n"; }
};

int main()
{
   some o;
   node* n = &o;

   test_visitor vis;
   apply_visitor(vis, n);
}


код visitor'а и apply_visitor можно сделать таким:

struct visitor
{
   virtual void visit(some&) = 0;
   virtual void visit(other&) = 0;
};

template<class Vis>
inline void apply_visitor(Vis& vis, node* n)
{
   struct visitor_impl : visitor
   {
      virtual void visit(some& n) { vis(n); }
      virtual void visit(other& n) { vis(n); }

      visitor_impl(Vis& vis) : vis(vis) {}
      Vis& vis;
   };

   visitor_impl impl(vis);
   n->accept(&impl);
}

void some::accept(visitor* v) { v->visit(*this); } // тут может быть нетривиальный код обхода структуры
void other::accept(visitor* v) { v->visit(*this); }


и всё бы тут вобщем-то и хорошо, но расстраивает то, что тут надо два раза перечислять классы — в visitor и в visitor_impl

хорошо бы как-нибудь шаблоны применить, чтоб этого избежать — к примеру visitor::visit совсем не обязательно должна быть виртуальной, она вполне может быть шаблонной

код полностью: http://codepad.org/RjBdzVAh
In Zen We Trust
visitor pattern
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.