source: trunk/yat/utility/iterator_traits.h @ 1566

Last change on this file since 1566 was 1565, checked in by Peter, 13 years ago

removed Policy from Container2DIterator - refs #398

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 8.5 KB
Line 
1#ifndef _theplu_yat_utility_iterator_traits_
2#define _theplu_yat_utility_iterator_traits_
3
4// $Id: iterator_traits.h 1565 2008-10-10 21:49:07Z peter $
5
6/*
7  Copyright (C) 2007 Jari Häkkinen, Peter Johansson
8  Copyright (C) 2008 Peter Johansson, Markus Ringnér
9
10  This file is part of the yat library, http://dev.thep.lu.se/yat
11
12  The yat library is free software; you can redistribute it and/or
13  modify it under the terms of the GNU General Public License as
14  published by the Free Software Foundation; either version 3 of the
15  License, or (at your option) any later version.
16
17  The yat library is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  General Public License for more details.
21
22  You should have received a copy of the GNU General Public License
23  along with yat. If not, see <http://www.gnu.org/licenses/>.
24*/
25
26#include "DataWeight.h"
27
28#include <iterator>
29
30namespace theplu {
31namespace yat {
32namespace utility {
33
34  /**
35    Struct to be used to make compile-time decision that Iterator is
36    unweighted, which is the default.
37   */ 
38  struct unweighted_iterator_tag {};
39   
40  /**
41    Struct to be used to make compile-time decision that Iterator is
42    weighted. Some algorithms come also in a weighted version and
43    this tag could be used to decide on using them (rather than
44    the corresponding unweighted algorithm).
45   */ 
46  struct weighted_iterator_tag {};
47
48
49  /**
50     \internal
51
52     used in weighted_iterator_traits
53  */
54  template <typename T>
55  struct weighted_iterator_traits_detail {
56    /**
57       default is a iterator unweighted
58    */
59    typedef unweighted_iterator_tag type;
60  }; 
61
62  /**
63      \internal
64
65      specialization for iterators with value type DataWeight
66  */
67  template <>
68  struct weighted_iterator_traits_detail<DataWeight> {
69    /**
70       Iterators with value type DataWeight is weighted
71     */
72    typedef weighted_iterator_tag type;
73  }; 
74
75  /**
76      Metafunction to decide whether an iterator is weighted or
77      non-weighted. This (default) implementation return unweighted,
78      unless value_type of iterator is DataWeight in which case
79      weighted is returned.
80  */
81  template <class T>
82  struct weighted_iterator_traits
83  {
84  private:
85    typedef typename std::iterator_traits<T>::value_type value;
86  public:
87    /**
88       \return weighted if value_type is DataWeight
89     */
90    typedef typename weighted_iterator_traits_detail<value>::type type;
91  };
92
93
94  /**
95     \internal
96
97    Metafunction that works on a pair weighted-unweighted types and
98    return weighted_type. The metafunction is specialized for
99    unweighted unweighted in which case unweighted is returned.
100   */
101  template <class T1, class T2>
102  struct unweighted_type_and {
103    /**
104       default return weighted_iterator_tag
105     */
106    typedef weighted_iterator_tag type;
107  };
108
109  /**
110     \internal
111
112    Specialization that sets type to be unweighted when both arguments
113    are unweighted
114   */
115  template <>
116  struct unweighted_type_and<unweighted_iterator_tag, unweighted_iterator_tag> {
117    /**
118       return unweighted_iterator_tag
119     */
120    typedef unweighted_iterator_tag type;
121  };
122
123  /**
124    struct used to determine if a pair of iterators should be treated
125    as weighted. If both iterators are unweighted, type is set to
126    unweighted else weighted.
127  */
128  template <class T1, class T2>
129  struct weighted_if_any2 {
130  private:
131    typedef typename weighted_iterator_traits<T1>::type w_type1;
132    typedef typename weighted_iterator_traits<T2>::type w_type2;
133  public:
134    /// return unweighted if both are unweighted
135    typedef typename unweighted_type_and<w_type1, w_type2>::type type;
136  };
137
138  /**
139    Same as weighted_iterator_traits2 but for 3 arguments.
140   */
141  template <class T1, class T2, class T3>
142  struct weighted_if_any3 {
143  private:
144    typedef typename weighted_if_any2<T1, T2>::type tmp;
145    typedef typename weighted_iterator_traits<T3>::type w_type3;
146  public:
147    /// return unweighted if all are unweighted
148    typedef typename unweighted_type_and<tmp, w_type3>::type type;
149  };
150
151  /// check (at compile time) that iterator is unweighted.
152  inline void check_iterator_is_unweighted(unweighted_iterator_tag x){} 
153
154  /**
155     check (at compile time) that iterator \a iter is unweighted. This
156     function is strictly not needed, but exists only for convenience.
157   */
158  template <class Iter>
159  void check_iterator_is_unweighted(Iter iter) 
160  { check_iterator_is_unweighted(typename 
161                                 weighted_iterator_traits<Iter>::type());
162  }
163
164
165  /**
166     \internal
167
168     This class is used in iterator_traits to separate different cases.
169
170     This the default implementation that could be used for unweighted
171     iterators.
172   */
173  template <typename Iter, typename T >
174  struct iterator_traits_detail
175  {
176    /**
177       for unweighted data_reference is reference
178    */
179    typedef typename std::iterator_traits<Iter>::reference data_reference;
180
181    /**
182       for unweighted weight_reference is a double
183    */
184    typedef double weight_reference;
185
186    /**
187       Constructor just checking that iterator is unweighted
188    */
189    iterator_traits_detail(void) 
190    { check_iterator_is_unweighted(typename 
191                                   weighted_iterator_traits<Iter>::type());
192    }
193   
194    /**
195       \return * \a iter
196    */
197    data_reference data(Iter iter) const { return *iter; }
198
199    /**
200       \return 1.0
201    */
202    weight_reference weight(Iter iter) const { return 1.0; }
203  };
204
205
206  /**
207     specialization for weighted iterator with reference DataWeight&
208   */
209  template <typename Iter>
210  struct iterator_traits_detail<Iter, DataWeight&> {
211    /**
212       for mutable weighted iterator data_reference is double&
213    */
214    typedef double& data_reference;
215
216    /**
217       for mutable weighted iterator weight_reference is double&
218    */
219    typedef double& weight_reference;
220
221    /**
222       \return reference to data of iterator
223    */
224    data_reference data(Iter iter) const { return iter->data(); }
225
226    /**
227       \return reference to weight of iterator
228    */
229    weight_reference weight(Iter iter) const { return iter->weight(); }
230  };
231
232
233  /**
234     specialization for weighted iterator with reference const DataWeight&
235   */
236  template <typename Iter>
237  struct iterator_traits_detail<Iter, const DataWeight&> {
238    /**
239       for read-only weighted iterator data_reference is const double&
240    */
241    typedef const double& data_reference;
242
243    /**
244       for read-only weighted iterator data_reference is const double&
245    */
246    typedef const double& weight_reference;
247
248    /**
249       \return const reference to data of iterator
250    */
251    data_reference data(Iter iter) const { return iter->data(); }
252
253    /**
254       \return const reference to weight of iterator
255    */
256    weight_reference weight(Iter iter) const { return iter->weight(); }
257  };
258
259
260  /**
261     specialization for weighted iterator with reference const DataWeight
262   */
263  template <typename Iter>
264  struct iterator_traits_detail<Iter, const DataWeight> {
265    /**
266       \brief data_reference
267    */
268    typedef const double data_reference;
269
270    /**
271       \brief weight_reference
272    */
273    typedef const double weight_reference;
274
275    /**
276       \return const reference to data of iterator
277    */
278    data_reference data(Iter iter) const { return (*iter).data(); }
279
280    /**
281       \return const reference to weight of iterator
282    */
283    weight_reference weight(Iter iter) const { return (*iter).weight(); }
284  };
285
286
287  /**
288     The purpose of this class is to allow polymorphism between
289     weighted and unweighted iterators. It allows to access data and
290     weight for both weighted and unweighted iterators.
291
292     This class works for unweighted iterators as well as weighted
293     iterators as long as they have reference type DataWeight& or
294     const DataWeight&.
295
296     For others, such as WeightedIterator for which reference type is
297     a proxy class, this class should be specialized. For adaptors
298     that have an underlying iterator (e.g. StrideIterator), this
299     class should be specialized, so the class also works when the
300     underlying is an iterator that is not covered by this class
301     e.g. WeightedIterator.
302   */ 
303  template <typename Iter>
304  struct iterator_traits {
305  private:
306    typedef typename std::iterator_traits<Iter>::reference reference;
307    typedef iterator_traits_detail<Iter, reference> traits;
308  public:
309    /**
310       data_reference (type returned by data(void) is determined by
311       iterator_traits_detail
312     */
313    typedef typename traits::data_reference data_reference;
314
315    /**
316       data_reference (type returned by data(void) is determined by
317       iterator_traits_detail
318     */
319    typedef typename traits::weight_reference weight_reference;
320
321    /**
322       \return data
323    */
324    data_reference data(Iter iter) const 
325    { return traits().data(iter); }
326
327    /**
328       \return weight
329     */
330    weight_reference weight(Iter iter) const 
331    { return traits().weight(iter); }
332
333  };
334
335
336}}} // of namespace utility, yat, and theplu
337
338#endif
Note: See TracBrowser for help on using the repository browser.