Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
accumulator.hh
1 // Copyright (C) 2007, 2008, 2009 EPITA Research and Development Laboratory (LRDE)
2 //
3 // This file is part of Olena.
4 //
5 // Olena is free software: you can redistribute it and/or modify it under
6 // the terms of the GNU General Public License as published by the Free
7 // Software Foundation, version 2 of the License.
8 //
9 // Olena is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with Olena. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free
18 // software project without restriction. Specifically, if other files
19 // instantiate templates or use macros or inline functions from this
20 // file, or you compile this file and link it with other files to produce
21 // an executable, this file does not by itself cause the resulting
22 // executable to be covered by the GNU General Public License. This
23 // exception does not however invalidate any other reasons why the
24 // executable file might be covered by the GNU General Public License.
25 
26 #ifndef MLN_CORE_CONCEPT_ACCUMULATOR_HH
27 # define MLN_CORE_CONCEPT_ACCUMULATOR_HH
28 
32 
33 # include <mln/core/concept/proxy.hh>
34 # include <mln/metal/fix_return.hh>
35 # include <mln/metal/const.hh>
36 # include <mln/trait/accumulators.hh>
37 
38 
39 namespace mln
40 {
41 
42  // Forward declaration.
43  template <typename E> struct Accumulator;
44 
45 
46  namespace convert
47  {
48 
49  namespace over_load
50  {
51 
52  template <typename A>
53  void
54  from_to_(const Accumulator<A>& from, mln_result(A)& to);
55 
56  } // end of namespace mln::convert::over_load
57 
58  } // end of namespace mln::convert
59 
60 
61  // Accumulator category flag type.
62  template <>
63  struct Accumulator<void>
64  {
65  typedef Proxy<void> super;
66  };
67 
68 
69 
77  template <typename E>
78  struct Accumulator : public Proxy<E>
79  {
80  typedef Accumulator<void> category;
81 
82  /*
83  typedef argument;
84  typedef result;
85  typedef q_result;
86 
87  void init();
88  void take(const argument& t);
89  void take(const E& other);
90 
91  q_result to_result() const;
92  operator q_result const;
93 
94  bool is_valid() const;
95  */
96 
101  template <typename T>
102  void take_as_init(const T& t); // 't' is either argument or E.
103 
105  template <typename T>
106  void take_as_init_(const T& t);
107 
108 
113  template <typename T>
114  void take_n_times(unsigned n, const T& t);
115 
117  template <typename T>
118  void take_n_times_(unsigned n, const T& t);
119 
120 
121  protected:
122  Accumulator();
123  };
124 
125 
126 # ifndef MLN_INCLUDE_ONLY
127 
128 
129  // convert::from_to_
130 
131  namespace convert
132  {
133 
134  namespace over_load
135  {
136 
137  template <typename A>
138  void
139  from_to_(const Accumulator<A>& from_, mln_result(A)& to)
140  {
141  const A& from = exact(from_);
142  if (from.is_valid())
143  to = from.to_result();
144  else
145  to = mln_result(A)();
146  }
147 
148  } // end of namespace mln::convert::over_load
149 
150  } // end of namespace mln::convert
151 
152 
153 
154  // Accumulator<E>
155 
156  template <typename E>
157  inline
158  Accumulator<E>::Accumulator()
159  {
160  typedef mln_argument(E) argument;
161  typedef mln_result(E) result;
162  typedef mln_q_result(E) q_result;
163 
164  void (E::*m1)() = & E::init;
165  m1 = 0;
166  void (E::*m2)(const argument&) = & E::take;
167  m2 = 0;
168  void (E::*m3)(const E&) = & E::take;
169  m3 = 0;
170 
171  q_result (E::*m4)() const = & E::to_result;
172  m4 = 0;
173  q_result (E::*m5)() const = & E::operator q_result;
174  m5 = 0;
175 
176  bool (E::*m6)() const = & E::is_valid;
177  m6 = 0;
178  }
179 
180 
181  // take_as_init
182 
183  template <typename E>
184  template <typename T>
185  void
186  Accumulator<E>::take_as_init(const T& t)
187  {
188  typedef mln_exact(T) T_;
189  typedef mlc_converts_to(T_, mln_argument(E)) t_is_argument;
190  typedef mlc_converts_to(T_, E) t_is_accumulator;
191  mlc_or(t_is_argument, t_is_accumulator)::check();
192 
193  // Dispatch.
194  exact(this)->take_as_init_(t);
195  }
196 
197  template <typename E>
198  template <typename T>
199  void
201  {
202  // Default impl.
203  exact(this)->init();
204  exact(this)->take(t);
205  }
206 
207 
208  // take n times
209 
210  template <typename E>
211  template <typename T>
212  void
213  Accumulator<E>::take_n_times(unsigned n, const T& t)
214  {
215  typedef mln_exact(T) T_;
216  typedef mlc_converts_to(T_, mln_argument(E)) t_is_argument;
217  typedef mlc_converts_to(T_, E) t_is_accumulator;
218  mlc_or(t_is_argument, t_is_accumulator)::check();
219 
220  if (n == 0u)
221  return;
222 
223  // Dispatch.
224  exact(this)->take_n_times_(n, t);
225  }
226 
227  template <typename E>
228  template <typename T>
229  void
230  Accumulator<E>::take_n_times_(unsigned n, const T& t)
231  {
232  // Default impl.
233  for (unsigned i = 0; i < n; ++i)
234  exact(this)->take(t);
235  }
236 
237 # endif // ! MLN_INCLUDE_ONLY
238 
239 } // end of namespace mln
240 
241 
242 #endif // ! MLN_CORE_CONCEPT_ACCUMULATOR_HH