Milena (Olena)  User documentation 2.0a Id
 All Classes Namespaces Functions Variables Typedefs Enumerator Groups Pages
complex_relative_iterator_sequence.hh
1 // Copyright (C) 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_TOPO_INTERNAL_COMPLEX_RELATIVE_ITERATOR_SEQUENCE_HH
27 # define MLN_TOPO_INTERNAL_COMPLEX_RELATIVE_ITERATOR_SEQUENCE_HH
28 
33 
34 # include <iosfwd>
35 
36 # include <mln/metal/equal.hh>
37 
38 # include <mln/core/concept/iterator.hh>
39 # include <mln/topo/complex.hh>
40 
41 
42 namespace mln
43 {
44 
45  namespace topo
46  {
47 
48  namespace internal
49  {
50 
51  template <typename I1>
52  struct const_face_type_
53  {
54  typedef typename I1::face_type F_;
55  typedef const F_& ret;
56  };
57 
58 
68  template <typename I1, typename I2, typename E>
69  class complex_relative_iterator_sequence : public Iterator<E>
70  {
71  typedef complex_relative_iterator_sequence<I1, I2, E> self_;
72 
73  public:
75  typedef typename I1::center_type center_type;
77  typedef typename I1::face_type face_type;
78 
81  complex_relative_iterator_sequence();
82  template <typename Fref>
83  complex_relative_iterator_sequence(const Fref& f_ref);
85 
89  void center_at(const center_type& c);
90 
92  bool is_valid() const;
94  void invalidate();
95 
97  void start();
99  void next_();
101 
105  operator typename const_face_type_<I1>::ret () const;
106  // that is: const face_type&
108 
109  protected:
111  void update_();
112 
113  protected:
115  I1 iter1_;
117  I2 iter2_;
118 
120  face_type f_;
121  };
122 
123 
125  template <typename I1, typename I2, typename E>
126  inline
127  std::ostream&
128  operator<<(std::ostream& ostr,
129  const complex_relative_iterator_sequence<I1, I2, E>& p);
130 
131 
132 
133 # ifndef MLN_INCLUDE_ONLY
134 
135  template <typename I1, typename I2, typename E>
136  inline
137  complex_relative_iterator_sequence<I1, I2, E>::complex_relative_iterator_sequence()
138  {
139  // Ensure I1 and I2 are compatible.
140  mlc_equal(typename I1::face_type, typename I2::face_type)::check();
141 
142  invalidate();
143  }
144 
145  template <typename I1, typename I2, typename E>
146  template <typename Fref>
147  inline
148  complex_relative_iterator_sequence<I1, I2, E>::complex_relative_iterator_sequence(const Fref& f_ref)
149  {
150  // Ensure I1 and I2 are compatible.
151  mlc_equal(typename I1::face_type, typename I2::face_type)::check();
152 
153  center_at(f_ref);
154  }
155 
156  template <typename I1, typename I2, typename E>
157  inline
158  void
159  complex_relative_iterator_sequence<I1, I2, E>::center_at(const center_type& c)
160  {
161  iter1_.center_at(c);
162  iter2_.center_at(c);
163  invalidate();
164  }
165 
166  template <typename I1, typename I2, typename E>
167  inline
168  bool
169  complex_relative_iterator_sequence<I1, I2, E>::is_valid() const
170  {
171  return iter1_.is_valid() || iter2_.is_valid();
172  }
173 
174  template <typename I1, typename I2, typename E>
175  inline
176  void
177  complex_relative_iterator_sequence<I1, I2, E>::invalidate()
178  {
179  iter1_.invalidate();
180  iter2_.invalidate();
181  }
182 
183  template <typename I1, typename I2, typename E>
184  inline
185  void
186  complex_relative_iterator_sequence<I1, I2, E>::start()
187  {
188  iter1_.start();
189  iter2_.start();
190  if (is_valid())
191  update_();
192  }
193 
194  template <typename I1, typename I2, typename E>
195  inline
196  void
197  complex_relative_iterator_sequence<I1, I2, E>::next_()
198  {
199  /* Iterator<E>::next() ensures that either iter1_ or iter2_
200  (or both) are valid before executing this method. */
201  if (iter1_.is_valid())
202  iter1_.next();
203  else
204  iter2_.next();
205  if (is_valid())
206  update_();
207  }
208 
209  template <typename I1, typename I2, typename E>
210  inline
211  void
212  complex_relative_iterator_sequence<I1, I2, E>::update_()
213  {
214  mln_precondition(is_valid());
215  if (iter1_.is_valid())
216  f_ = iter1_;
217  else
218  f_ = iter2_;
219  }
220 
221  template <typename I1, typename I2, typename E>
222  inline
223  complex_relative_iterator_sequence<I1, I2, E>::operator typename const_face_type_<I1>::ret () const
224  {
225  return f_;
226  }
227 
228 
229  template <typename I1, typename I2, typename E>
230  inline
231  std::ostream&
232  operator<<(std::ostream& ostr,
233  const complex_relative_iterator_sequence<I1, I2, E>& p)
234  {
235  return ostr << typename I1::face_type(p);
236  }
237 
238 # endif // ! MLN_INCLUDE_ONLY
239 
240  } // end of namespace mln::topo::internal
241 
242  } // end of namespace mln::topo
243 
244 } // end of namespace mln
245 
246 #endif // ! MLN_TOPO_INTERNAL_COMPLEX_RELATIVE_ITERATOR_SEQUENCE_HH