Milena (Olena)
User documentation 2.0a Id
|
00001 // Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE) 00002 // 00003 // This file is part of Olena. 00004 // 00005 // Olena is free software: you can redistribute it and/or modify it under 00006 // the terms of the GNU General Public License as published by the Free 00007 // Software Foundation, version 2 of the License. 00008 // 00009 // Olena is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Olena. If not, see <http://www.gnu.org/licenses/>. 00016 // 00017 // As a special exception, you may use this file as part of a free 00018 // software project without restriction. Specifically, if other files 00019 // instantiate templates or use macros or inline functions from this 00020 // file, or you compile this file and link it with other files to produce 00021 // an executable, this file does not by itself cause the resulting 00022 // executable to be covered by the GNU General Public License. This 00023 // exception does not however invalidate any other reasons why the 00024 // executable file might be covered by the GNU General Public License. 00025 00026 #ifndef MLN_CORE_CONCEPT_ACCUMULATOR_HH 00027 # define MLN_CORE_CONCEPT_ACCUMULATOR_HH 00028 00032 00033 # include <mln/core/concept/proxy.hh> 00034 # include <mln/metal/fix_return.hh> 00035 # include <mln/metal/const.hh> 00036 # include <mln/trait/accumulators.hh> 00037 00038 00039 namespace mln 00040 { 00041 00042 // Forward declaration. 00043 template <typename E> struct Accumulator; 00044 00045 00046 namespace convert 00047 { 00048 00049 namespace over_load 00050 { 00051 00052 template <typename A> 00053 void 00054 from_to_(const Accumulator<A>& from, mln_result(A)& to); 00055 00056 } // end of namespace mln::convert::over_load 00057 00058 } // end of namespace mln::convert 00059 00060 00061 // Accumulator category flag type. 00062 template <> 00063 struct Accumulator<void> 00064 { 00065 typedef Proxy<void> super; 00066 }; 00067 00068 00069 00077 template <typename E> 00078 struct Accumulator : public Proxy<E> 00079 { 00080 typedef Accumulator<void> category; 00081 00082 /* 00083 typedef argument; 00084 typedef result; 00085 typedef q_result; 00086 00087 void init(); 00088 void take(const argument& t); 00089 void take(const E& other); 00090 00091 q_result to_result() const; 00092 operator q_result const; 00093 00094 bool is_valid() const; 00095 */ 00096 00101 template <typename T> 00102 void take_as_init(const T& t); // 't' is either argument or E. 00103 00105 template <typename T> 00106 void take_as_init_(const T& t); 00107 00108 00113 template <typename T> 00114 void take_n_times(unsigned n, const T& t); 00115 00117 template <typename T> 00118 void take_n_times_(unsigned n, const T& t); 00119 00120 00121 protected: 00122 Accumulator(); 00123 }; 00124 00125 00126 # ifndef MLN_INCLUDE_ONLY 00127 00128 00129 // convert::from_to_ 00130 00131 namespace convert 00132 { 00133 00134 namespace over_load 00135 { 00136 00137 template <typename A> 00138 void 00139 from_to_(const Accumulator<A>& from_, mln_result(A)& to) 00140 { 00141 const A& from = exact(from_); 00142 if (from.is_valid()) 00143 to = from.to_result(); 00144 else 00145 to = mln_result(A)(); 00146 } 00147 00148 } // end of namespace mln::convert::over_load 00149 00150 } // end of namespace mln::convert 00151 00152 00153 00154 // Accumulator<E> 00155 00156 template <typename E> 00157 inline 00158 Accumulator<E>::Accumulator() 00159 { 00160 typedef mln_argument(E) argument; 00161 typedef mln_result(E) result; 00162 typedef mln_q_result(E) q_result; 00163 00164 void (E::*m1)() = & E::init; 00165 m1 = 0; 00166 void (E::*m2)(const argument&) = & E::take; 00167 m2 = 0; 00168 void (E::*m3)(const E&) = & E::take; 00169 m3 = 0; 00170 00171 q_result (E::*m4)() const = & E::to_result; 00172 m4 = 0; 00173 q_result (E::*m5)() const = & E::operator q_result; 00174 m5 = 0; 00175 00176 bool (E::*m6)() const = & E::is_valid; 00177 m6 = 0; 00178 } 00179 00180 00181 // take_as_init 00182 00183 template <typename E> 00184 template <typename T> 00185 void 00186 Accumulator<E>::take_as_init(const T& t) 00187 { 00188 typedef mln_exact(T) T_; 00189 typedef mlc_converts_to(T_, mln_argument(E)) t_is_argument; 00190 typedef mlc_converts_to(T_, E) t_is_accumulator; 00191 mlc_or(t_is_argument, t_is_accumulator)::check(); 00192 00193 // Dispatch. 00194 exact(this)->take_as_init_(t); 00195 } 00196 00197 template <typename E> 00198 template <typename T> 00199 void 00200 Accumulator<E>::take_as_init_(const T& t) 00201 { 00202 // Default impl. 00203 exact(this)->init(); 00204 exact(this)->take(t); 00205 } 00206 00207 00208 // take n times 00209 00210 template <typename E> 00211 template <typename T> 00212 void 00213 Accumulator<E>::take_n_times(unsigned n, const T& t) 00214 { 00215 typedef mln_exact(T) T_; 00216 typedef mlc_converts_to(T_, mln_argument(E)) t_is_argument; 00217 typedef mlc_converts_to(T_, E) t_is_accumulator; 00218 mlc_or(t_is_argument, t_is_accumulator)::check(); 00219 00220 if (n == 0u) 00221 return; 00222 00223 // Dispatch. 00224 exact(this)->take_n_times_(n, t); 00225 } 00226 00227 template <typename E> 00228 template <typename T> 00229 void 00230 Accumulator<E>::take_n_times_(unsigned n, const T& t) 00231 { 00232 // Default impl. 00233 for (unsigned i = 0; i < n; ++i) 00234 exact(this)->take(t); 00235 } 00236 00237 # endif // ! MLN_INCLUDE_ONLY 00238 00239 } // end of namespace mln 00240 00241 00242 #endif // ! MLN_CORE_CONCEPT_ACCUMULATOR_HH