00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
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   
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     } 
00057 
00058   } 
00059 
00060 
00061   
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 
00084 
00085 
00086 
00087 
00088 
00089 
00090 
00091 
00092 
00093 
00094 
00095 
00096 
00101     template <typename T>
00102     void take_as_init(const T& t); 
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   
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     } 
00149 
00150   } 
00151 
00152 
00153 
00154   
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   
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     
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     
00203     exact(this)->init();
00204     exact(this)->take(t);
00205   }
00206 
00207 
00208   
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     
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     
00233     for (unsigned i = 0; i < n; ++i)
00234       exact(this)->take(t);
00235   }
00236 
00237 # endif // ! MLN_INCLUDE_ONLY
00238 
00239 } 
00240 
00241 
00242 #endif // ! MLN_CORE_CONCEPT_ACCUMULATOR_HH