visitor.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #ifndef LASS_GUARDIAN_OF_INCLUSION_UTIL_VISITOR_H
00044 #define LASS_GUARDIAN_OF_INCLUSION_UTIL_VISITOR_H
00045
00046 namespace lass
00047 {
00048 namespace util
00049 {
00050
00051 class BadVisit: public Exception
00052 {
00053 public:
00054 BadVisit(const std::string& msg, const std::string& loc): Exception(msg, loc) {}
00055 private:
00056 LASS_UTIL_EXCEPTION_PRIVATE_IMPL(BadVisit)
00057 };
00058
00059
00060
00061 class LASS_DLL VisitorBase
00062 {
00063 public:
00064 virtual ~VisitorBase();
00065 protected:
00066 VisitorBase();
00067 };
00068
00069
00070
00071 template <typename T>
00072 class Visitor
00073 {
00074 public:
00075 void preVisit(T& visitable)
00076 {
00077 doPreVisit(visitable);
00078 }
00079 void postVisit(T& visitable)
00080 {
00081 doPostVisit(visitable);
00082 }
00083 private:
00084 virtual void doPreVisit(T& visitable) = 0;
00085 virtual void doPostVisit(T& visitable) {}
00086 };
00087
00088
00089
00090 struct ThrowOnUnknownVisit
00091 {
00092 template <typename T> static void onUnknownPreVisit(VisitorBase& visitor, T& visitable)
00093 {
00094 LASS_THROW_EX(BadVisit, "unkown previsit on type '" << typeid(T).name() << "'.");
00095 }
00096 template <typename T> static void onUnknownPostVisit(VisitorBase& visitor, T& visitable)
00097 {
00098 LASS_THROW_EX(BadVisit, "unkown postvisit on type '" << typeid(T).name() << "'.");
00099 }
00100 };
00101
00102
00103 struct IgnoreUnknownVisit
00104 {
00105 template <typename T> static void onUnknownPreVisit(VisitorBase& visitor, T& visitable) {}
00106 template <typename T> static void onUnknownPostVisit(VisitorBase& visitor, T& visitable) {}
00107 };
00108
00109
00110
00111 template <typename CatchAll = ThrowOnUnknownVisit>
00112 class VisitableBase
00113 {
00114 public:
00115 virtual ~VisitableBase() {}
00116
00117 void accept(VisitorBase& visitor) { doAccept(visitor); }
00118
00119 template <typename T>
00120 static void preAccept(VisitorBase& visitor, T& visitable)
00121 {
00122 if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&visitor))
00123 {
00124 p->preVisit(visitable);
00125 }
00126 else
00127 {
00128 CatchAll::onUnknownPreVisit(visitor, visitable);
00129 }
00130 }
00131
00132 template <typename T>
00133 static void postAccept(VisitorBase& visitor, T& visitable)
00134 {
00135 if (Visitor<T>* p = dynamic_cast<Visitor<T>*>(&visitor))
00136 {
00137 p->postVisit(visitable);
00138 }
00139 else
00140 {
00141 CatchAll::onUnknownPostVisit(visitor, visitable);
00142 }
00143 }
00144
00145 private:
00146
00147 virtual void doAccept(VisitorBase& visitor) = 0;
00148 };
00149
00150 #define LASS_UTIL_VISITOR_DO_ACCEPT\
00151 void doAccept(::lass::util::VisitorBase& visitor)\
00152 {\
00153 preAccept(visitor, *this);\
00154 postAccept(visitor, *this);\
00155 }
00156
00157 }
00158 }
00159
00160 #endif
00161
00162