00001 #ifndef QPID_AMQP_0_10_APPLY_H
00002 #define QPID_AMQP_0_10_APPLY_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <boost/optional.hpp>
00025
00026 namespace qpid {
00027 namespace amqp_0_10 {
00028
00029 template <class F, class R=typename F::result_type> struct FunctionAndResult {
00030 F* functor;
00031 boost::optional<R> result;
00032
00033 FunctionAndResult() : functor(0) {}
00034 template <class T> void invoke(T& t) { result=(*functor)(t); }
00035 template <class T> void invoke(const T& t) { result=(*functor)(t); }
00036 R getResult() { return *result; }
00037 };
00038
00039
00040 template <class F> struct FunctionAndResult<F, void> {
00041 F* functor;
00042
00043 FunctionAndResult() : functor(0) {}
00044 template <class T> void invoke(T& t) { (*functor)(t); }
00045 void getResult() {}
00046 };
00047
00048
00049 template <class Visitable> struct VisitorType {
00050 typedef typename Visitable::Visitor type;
00051 };
00052 template <class Visitable> struct VisitorType<const Visitable> {
00053 typedef typename Visitable::ConstVisitor type;
00054 };
00055
00056 template <class Visitor, class F>
00057 struct ApplyVisitorBase : public Visitor, public FunctionAndResult<F> {};
00058
00059
00060 template <class Visitable, class F> struct ApplyVisitor;
00061
00066 template <class F, class Visitable>
00067 typename F::result_type apply(F& functor, Visitable& visitable) {
00068 ApplyVisitor<typename VisitorType<Visitable>::type, F> visitor;
00069 visitor.functor=&functor;
00070 visitable.accept(visitor);
00071 return visitor.getResult();
00072 }
00073
00074 template <class F, class Visitable>
00075 typename F::result_type apply(const F& functor, Visitable& visitable) {
00076 ApplyVisitor<typename VisitorType<Visitable>::type, const F> visitor;
00077 visitor.functor=&functor;
00078 visitable.accept(visitor);
00079 return visitor.getResult();
00080 }
00081
00082 template <class R> struct ApplyFunctor { typedef R result_type; };
00083
00084 }}
00085
00086 #endif