|
libpsynth 0.2.1
|
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_ */
1.7.4