Files
core/ASCOfficeOdfFileW/source/OdfFormat/visitor.h

144 lines
3.4 KiB
C++

#ifndef _CPDOCCORE_VISITOR_H_INCLUDED_
#define _CPDOCCORE_VISITOR_H_INCLUDED_
/*
Ñõåìà ðàáîòû ñ visitor:
äëÿ êëàññîâ, êîòîðûå ìîãóò áûòü ïîñåùåíû visitor-îì:
1. íàñëåäóåì îò base_visitable
2. îáúÿâëÿåì âíóòðè ìàêðîñ CPDOCCORE_DEFINE_VISITABLE()
class example_visitable_element: public base_visitable
{
// ...
public:
CPDOCCORE_DEFINE_VISITABLE();
// ...
};
Äëÿ ñîçäàíèÿ ãîñòÿ:
1. íàñëåäóåì ãîñòÿ îò base_visitor
2. íàñëåäóåì ãîñòÿ(âèçèòîð) îò const_visitor<visitable_element1>/visitor<visitable_element1>,
const_visitor<visitable_element2>/visitor<visitable_element2>, è ò.ä.
äëÿ êàæäîãî èç ýëåìåíòîâ, êîòîûðå ìîæåò ïîñåòèòü âèçèòîð
3. îáúÿâëÿåì äëÿ êàæäîãî èç ýëåìåíòîâ ìåòîä
virtual void visit(const visitable_element1& val);
virtual void visit(const visitable_element2& val);
è ò.ä.
(â ñëó÷àå íåêîíñòàòíîñòè - óáèðàåì const)
class table_round : public base_visitor,
public const_visitor<office_body>,
public const_visitor<office_spreadsheet>,
public const_visitor<table_table>
{
virtual void visit(const office_body& val)
{
// ...
}
virtual void visit(const office_spreadsheet& val)
{
// ...
}
virtual void visit(const table_table& val)
{
// ...
}
};
Äëÿ îðãàíèçàöèè îáõîäà:
1. Ñîçäàåì âèçèòîð
2. Âûïîëíÿåì accept äëÿ êîðíåâîãî ýëåìåíòà
office_element * root;
/// ...
table_round tableRoundVisitor;
root->accept(tableRoundVisitor);
Âíèìàíèå! Âèçèòîð ÑÀÌ îïðåäåëÿåò ïðàâèëà îáõîäà âíóòðåííèõ âåðøèí, ò.å. âíóòðè êàæäîé ôóíêöèè ïîñåùåíèÿ òðåáóåòñÿ íàïèñàòü íàïðèìåð
virtual void visit(const office_body& val)
{
val.content_->accept(*this);
}
*/
namespace cpdoccore {
class base_visitor
{
public:
virtual ~base_visitor() {}
virtual void on_not_impl(std::string const & message) = 0;
};
template <class T>
class visitor
{
public:
virtual void visit(T&) = 0;
// virtual void visit(T const& t) = 0;
};
template <class T>
class const_visitor
{
public:
virtual void visit(T const& t) = 0;
};
class base_visitable
{
public:
virtual ~base_visitable() {};
virtual void accept(base_visitor &) = 0;
virtual void accept(base_visitor &) const = 0;
protected:
template <class T>
static void accept_impl(T& visited, base_visitor & guest)
{
if (visitor<T> * p = dynamic_cast< visitor<T> * >(&guest))
{
return p->visit(visited);
}
else
{
guest.on_not_impl(typeid(visited).name());
}
}
template <class T>
static void accept_impl(T const& visited, base_visitor & guest)
{
if (const_visitor<T> * p = dynamic_cast< const_visitor<T> * >(&guest))
{
return p->visit(visited);
}
else
{
guest.on_not_impl(typeid(visited).name());
}
}
};
#define CPDOCCORE_DEFINE_VISITABLE() \
virtual void accept(base_visitor& guest)\
{\
return accept_impl(*this, guest);\
}\
virtual void accept(base_visitor& guest) const\
{\
return accept_impl(*this, guest);\
}
}
#endif