mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-07-11 10:59:17 +08:00
144 lines
3.4 KiB
C++
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
|