simple_visitor.hh

00001 /* vim: set sw=4 sts=4 et foldmethod=syntax : */
00002 
00003 /*
00004  * Copyright (c) 2008 Ciaran McCreesh
00005  *
00006  * This file is part of the Paludis package manager. Paludis is free software;
00007  * you can redistribute it and/or modify it under the terms of the GNU General
00008  * Public License version 2, as published by the Free Software Foundation.
00009  *
00010  * Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
00011  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00013  * details.
00014  *
00015  * You should have received a copy of the GNU General Public License along with
00016  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00017  * Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 #ifndef PALUDIS_GUARD_PALUDIS_UTIL_SIMPLE_VISITOR_HH
00021 #define PALUDIS_GUARD_PALUDIS_UTIL_SIMPLE_VISITOR_HH 1
00022 
00023 #include <paludis/util/simple_visitor-fwd.hh>
00024 #include <paludis/util/no_type.hh>
00025 
00026 namespace paludis
00027 {
00028     template <>
00029     struct DeclareAbstractVisitMethods<TypeListTail>
00030     {
00031         void forward_visit(const NoType<0u> &);
00032     };
00033 
00034     template <typename TypeList_>
00035     class DeclareAbstractVisitMethods :
00036         public virtual DeclareAbstractVisitMethods<typename TypeList_::Tail>
00037     {
00038         public:
00039             using DeclareAbstractVisitMethods<typename TypeList_::Tail>::forward_visit;
00040 
00041             virtual void forward_visit(typename TypeList_::Item &) = 0;
00042     };
00043 
00044     template <typename TypeList_>
00045     class WrappedVisitorBase :
00046         public virtual DeclareAbstractVisitMethods<TypeList_>
00047     {
00048     };
00049 
00050     template <typename RealClass_>
00051     class ImplementVisitMethods<RealClass_, TypeListTail>
00052     {
00053         public:
00054             void forward_visit(const NoType<1u> &);
00055     };
00056 
00057     template <typename RealClass_, typename TypeList_>
00058     class ImplementVisitMethods :
00059         public virtual DeclareAbstractVisitMethods<TypeList_>,
00060         public ImplementVisitMethods<RealClass_, typename TypeList_::Tail>
00061     {
00062         public:
00063             using ImplementVisitMethods<RealClass_, typename TypeList_::Tail>::forward_visit;
00064 
00065             virtual void forward_visit(typename TypeList_::Item & n)
00066             {
00067                 /* avoid gcc being too clever about noreturn */
00068                 if (this)
00069                     static_cast<RealClass_ *>(this)->perform_visit(n);
00070             }
00071     };
00072 
00073     template <typename TypeList_, typename UnwrappedVisitor_>
00074     class WrappedVoidResultVisitor :
00075         public WrappedVisitorBase<TypeList_>,
00076         public ImplementVisitMethods<WrappedVoidResultVisitor<TypeList_, UnwrappedVisitor_>, TypeList_>
00077     {
00078         private:
00079             UnwrappedVisitor_ & _unwrapped_visitor;
00080 
00081         public:
00082             WrappedVoidResultVisitor(UnwrappedVisitor_ & v) :
00083                 _unwrapped_visitor(v)
00084             {
00085             }
00086 
00087             template <typename C_>
00088             void perform_visit(C_ & t)
00089             {
00090                 _unwrapped_visitor.visit(t);
00091             }
00092     };
00093 
00094     template <typename TypeList_, typename Result_, typename UnwrappedVisitor_>
00095     class WrappedNonVoidResultVisitor :
00096             public WrappedVisitorBase<TypeList_>,
00097             public ImplementVisitMethods<WrappedNonVoidResultVisitor<TypeList_, Result_, UnwrappedVisitor_>,
00098                 TypeList_>
00099     {
00100         private:
00101             UnwrappedVisitor_ & _unwrapped_visitor;
00102 
00103         public:
00104             Result_ result;
00105 
00106             WrappedNonVoidResultVisitor(UnwrappedVisitor_ & v, const Result_ & r) :
00107                 _unwrapped_visitor(v),
00108                 result(r)
00109             {
00110             }
00111 
00112             template <typename C_>
00113             void perform_visit(C_ & t)
00114             {
00115                 result = _unwrapped_visitor.visit(t);
00116             }
00117     };
00118 
00119     template <typename BaseClass_, typename VisitableTypeList_>
00120     class DeclareAbstractAcceptMethods
00121     {
00122         private:
00123             virtual void _real_accept(WrappedVisitorBase<VisitableTypeList_> &) = 0;
00124             virtual void _real_accept_const(WrappedVisitorBase<typename MakeTypeListConst<VisitableTypeList_>::Type> &) const = 0;
00125 
00126         public:
00127             typedef VisitableTypeList_ VisitableTypeList;
00128 
00129             template <typename UnwrappedVisitor_>
00130             void accept(UnwrappedVisitor_ & v)
00131             {
00132                 WrappedVoidResultVisitor<VisitableTypeList_, UnwrappedVisitor_> vv(v);
00133                 _real_accept(vv);
00134             }
00135 
00136             template <typename UnwrappedVisitor_>
00137             void accept(UnwrappedVisitor_ & v) const
00138             {
00139                 WrappedVoidResultVisitor<typename MakeTypeListConst<VisitableTypeList_>::Type, UnwrappedVisitor_> vv(v);
00140                 _real_accept_const(vv);
00141             }
00142 
00143             template <typename Result_, typename UnwrappedVisitor_>
00144             Result_ accept_returning(UnwrappedVisitor_ & v, const Result_ & r = Result_())
00145             {
00146                 WrappedNonVoidResultVisitor<VisitableTypeList_, Result_, UnwrappedVisitor_> vv(v, r);
00147                 _real_accept(vv);
00148                 return vv.result;
00149             }
00150 
00151             template <typename Result_, typename UnwrappedVisitor_>
00152             Result_ accept_returning(UnwrappedVisitor_ & v, const Result_ & r = Result_()) const
00153             {
00154                 WrappedNonVoidResultVisitor<typename MakeTypeListConst<VisitableTypeList_>::Type, Result_, UnwrappedVisitor_> vv(v, r);
00155                 _real_accept_const(vv);
00156                 return vv.result;
00157             }
00158     };
00159 
00160     template <typename BaseClass_, typename RealClass_>
00161     class ImplementAcceptMethods :
00162         public virtual DeclareAbstractAcceptMethods<BaseClass_, typename BaseClass_::VisitableTypeList>
00163     {
00164         private:
00165             void _real_accept(WrappedVisitorBase<typename BaseClass_::VisitableTypeList> & v)
00166             {
00167                 v.forward_visit(*static_cast<RealClass_ *>(this));
00168             };
00169 
00170             void _real_accept_const(WrappedVisitorBase<typename MakeTypeListConst<typename BaseClass_::VisitableTypeList>::Type> & v) const
00171             {
00172                 v.forward_visit(*static_cast<const RealClass_ *>(this));
00173             };
00174     };
00175 }
00176 
00177 #endif

Generated on Mon Sep 21 10:36:08 2009 for paludis by  doxygen 1.5.4