libpsynth 0.2.1
/home/raskolnikov/dev/psynth/trunk/src/psynth/base/c3_class.hpp
Go to the documentation of this file.
00001 
00021 /*
00022  *  Copyright (C) 2010 Juan Pedro Bolivar Puente
00023  *
00024  *  This file is part of Psychosynth.
00025  *   
00026  *  Psychosynth is free software: you can redistribute it and/or modify
00027  *  it under the terms of the GNU General Public License as published by
00028  *  the Free Software Foundation, either version 3 of the License, or
00029  *  (at your option) any later version.
00030  *
00031  *  Psychosynth is distributed in the hope that it will be useful,
00032  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00033  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00034  *  GNU General Public License for more details.
00035  *
00036  *  You should have received a copy of the GNU General Public License
00037  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00038  *
00039  */
00040 
00041 #ifndef PSYNTH_BASE_C3_CLASS_H_
00042 #define PSYNTH_BASE_C3_CLASS_H_
00043 
00044 #include <boost/mpl/eval_if.hpp>
00045 #include <boost/mpl/empty.hpp>
00046 #include <boost/mpl/lambda.hpp>
00047 #include <boost/mpl/transform.hpp>
00048 #include <boost/mpl/contains.hpp>
00049 #include <boost/mpl/pop_front.hpp>
00050 #include <boost/mpl/push_front.hpp>
00051 #include <boost/mpl/front.hpp>
00052 #include <boost/mpl/reverse.hpp>
00053 #include <boost/mpl/inherit_linearly.hpp>
00054 #include <boost/mpl/list.hpp>
00055 
00056 #include <psynth/base/meta.hpp>
00057 
00058 namespace psynth
00059 {
00060 namespace base
00061 {
00062 
00063 namespace detail
00064 {
00065 
00066 template<class ReversedPartialResult, class RemainingInputs>
00067 struct merge_lists;
00068 
00069 template<class ReversedPartialResult, class RemainingInputs>
00070 struct do_merge_lists
00071 {
00072     template<class C>
00073     struct candidate
00074     {
00075         typedef typename C::type cls;
00076 
00077         template<class L>
00078         struct tail_p : public mpl::contains<
00079             typename safe_pop_front<L>::type, cls> {};
00080         
00081         typedef typename mpl::if_<
00082             mpl::not_<any_p<RemainingInputs, mpl::quote1<tail_p> > >,
00083             cls, mpl::false_>::type type;
00084     };
00085 
00086     template <class L>
00087     struct candidate_at_head :
00088         public mpl::eval_if<mpl::not_<typename mpl::empty<L>::type >,
00089                             candidate<mpl::front<L> >,
00090                             mpl::false_> {};
00091 
00092     template <class L>
00093     struct candidate_at_head_p :
00094         public mpl::not_<boost::is_same<typename candidate_at_head<L>::type,
00095                                         mpl::false_> > {};
00096     
00097     typedef typename mpl::find_if<
00098         RemainingInputs,
00099         mpl::quote1<candidate_at_head_p> >::type next_iter;
00100 
00101     typedef mpl::not_<
00102         boost::is_same<
00103             next_iter,
00104             typename mpl::end<RemainingInputs>::type > > is_consistent;
00105 
00106     BOOST_MPL_ASSERT_MSG(is_consistent::value,
00107                          PSYNTH_C3_LINEARIZE_INCONSISTENT_HIERARCHY,
00108                          (ReversedPartialResult, RemainingInputs));
00109 
00110     typedef typename mpl::front<typename mpl::deref<next_iter>::type>::type next;
00111     
00112     //BOOST_MPL_ASSERT_MSG(false, PSYNTH_SHOW_NEXT, (next));
00113     
00114     template<class L>
00115     struct remove_next :
00116         public mpl::eval_if<
00117         typename boost::is_same<typename safe_front<L>::type, next>::type,
00118         mpl::pop_front<L>,
00119         mpl::identity<L> > {};
00120     
00121     typedef typename merge_lists<
00122         typename mpl::push_front<ReversedPartialResult, next>::type,
00123         typename mpl::transform<RemainingInputs,
00124                                 mpl::quote1<remove_next> >::type >::type type;
00125 };
00126 
00127 template<class ReversedPartialResult, class RemainingInputs>
00128 struct merge_lists : public mpl::eval_if<
00129     typename every_p<RemainingInputs, mpl::quote1<mpl::empty> >::type,
00130     mpl::reverse<ReversedPartialResult>,
00131     do_merge_lists<ReversedPartialResult, RemainingInputs> > {};
00132 
00133 } /* namespace detail */
00134 
00135 template<class ClsDef>
00136 struct direct_superclasses
00137 {
00138     typedef typename ClsDef::bases type;
00139 };
00140 
00141 template<class ClsDef>
00142 struct all_superclasses
00143 {
00144     typedef typename direct_superclasses<ClsDef>::type superclasses;
00145     
00146     typedef typename detail::merge_lists<
00147         mpl::list<ClsDef>,
00148         typename concat<
00149             typename mpl::transform<
00150                 superclasses,
00151                 mpl::quote1<all_superclasses> >::type,
00152             mpl::list<superclasses> >::type >::type type;
00153 };
00154 
00155 namespace detail
00156 {
00157 
00158 template <class ClsDefList, bool Empty>
00159 struct c3_inheriter;
00160 
00161 template<class ClsDefList>
00162 struct c3_inheriter<ClsDefList, false> :
00163         public mpl::front<ClsDefList>::type::template impl<
00164     c3_inheriter<typename mpl::pop_front<ClsDefList>::type,
00165                  mpl::empty<
00166                      typename mpl::pop_front<ClsDefList>::type >::type::value
00167                  > >
00168 {
00169     typedef typename mpl::front<ClsDefList>::type c3_type;    
00170 };
00171 
00172 template<class ClsDefList>
00173 struct c3_inheriter<ClsDefList, true> :
00174     public mpl::empty_base
00175 {
00176 //    virtual void print (std::ostream& os) {}
00177 };
00178 
00179 } /* namespace detail */
00180 
00181 template<class ClsDef>
00182 struct generate_c3_hierarchy
00183 {    
00184     typedef typename all_superclasses<ClsDef>::type classes;
00185 
00186     //BOOST_MPL_ASSERT_MSG(false, PSYNTH_SHOW_CLASSES, (classes));
00187 
00188     typedef typename detail::c3_inheriter<
00189         classes, mpl::empty<classes>::type::value> type;
00190 };
00191 
00192 template<class ClsImpl>
00193 struct get_c3_type
00194 {
00195     typedef typename ClsImpl::c3_type type;
00196 };
00197 
00198 #define PSYNTH_C3_CLASS_BEGIN(cls_name, ...)                            \
00199     struct cls_name ## _c3                                              \
00200     {                                                                   \
00201     typedef ::boost::mpl::transform< ::boost::mpl::list<__VA_ARGS__>, ::boost::mpl::quote1< ::psynth::base::get_c3_type > >::type bases; \
00202     template<class Super>                                               \
00203     class impl : public Super
00204 
00205 #define PSYNTH_C3_CLASS_END(cls_name)                                   \
00206     };                                                                  \
00207     typedef ::psynth::base::generate_c3_hierarchy<cls_name ## _c3>::type cls_name;
00208 
00209 } /* namespace base */
00210 } /* namespace psynth */
00211 
00212 #endif /* PSYNTH_BASE_C3_CLASS_H_ */