#ifndef __XIOS_VISITABLE_HPP #define __XIOS_VISITABLE_HPP #include "visitor.hpp" #include namespace xios { template struct DefaultCatchAll { static R OnUnknownVisitor(ParamType&, CBaseVisitor&) { return R(); } }; //////////////////////////////////////////////////////////////////////////////// // class template CBaseVisitable //////////////////////////////////////////////////////////////////////////////// template < typename R = void, template class CatchAll = DefaultCatchAll, bool ConstVisitable = false > class CBaseVisitable; template class CatchAll> class CBaseVisitable { public: typedef R ReturnType; virtual ~CBaseVisitable() {} virtual ReturnType apply(CBaseVisitor&) = 0; virtual void apply(std::vector&) = 0; protected: // give access only to the hierarchy template static ReturnType applyImpl(T& visited, CBaseVisitor& guest) { // Apply the CVisitor if (CVisitor* p = dynamic_cast*>(&guest)) { return p->operate(visited); } return CatchAll::OnUnknownVisitor(visited, guest); } }; template class CatchAll> class CBaseVisitable { public: typedef R ReturnType; virtual ~CBaseVisitable() {} virtual ReturnType apply(CBaseVisitor&) const = 0; virtual void apply(std::vector&) const = 0; protected: // give access only to the hierarchy template static ReturnType applyImpl(const T& visited, CBaseVisitor& guest) { // Apply the CVisitor if (CVisitor* p = dynamic_cast*>(&guest)) { return p->operate(visited); } return CatchAll::OnUnknownVisitor(const_cast(visited), guest); } }; //////////////////////////////////////////////////////////////////////////////// /// Put it in every class that you want to make guest /// functions (in addition to deriving it from CBaseVisitable) //////////////////////////////////////////////////////////////////////////////// #define DEFINE_VISITABLE() \ virtual ReturnType apply(::xios::CBaseVisitor& guest) \ { return applyImpl(*this, guest); } \ virtual void apply(std::vector& guests) \ { \ for (std::vector::iterator it = guests.begin(); it != guests.end(); ++it) \ apply(*(*it)); \ } //////////////////////////////////////////////////////////////////////////////// /// Put it in every class that you want to make guest by const member /// functions (in addition to deriving it from CBaseVisitable) //////////////////////////////////////////////////////////////////////////////// #define DEFINE_CONST_VISITABLE() \ virtual ReturnType apply(::xios::CBaseVisitor& guest) const \ { return applyImpl(*this, guest); } \ virtual void apply(std::vector& guests) const \ { \ for (std::vector::iterator it = guests.begin(); it != guests.end(); ++it) \ apply(*(*it)); \ } class CGenericTransformation : public virtual CBaseVisitable<> { public: DEFINE_VISITABLE() }; } #endif // __XIOS_VISITABLE_HPP