source: trunk/yat/utility/WeightedIteratorArchetype.h @ 3579

Last change on this file since 3579 was 3579, checked in by Peter, 5 years ago

merge release 0.14 into trunk

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.2 KB
Line 
1#ifndef _theplu_yat_utility_weighted_iterator_archetype
2#define _theplu_yat_utility_weighted_iterator_archetype
3
4// $Id: WeightedIteratorArchetype.h 3579 2017-01-16 03:54:43Z peter $
5
6/*
7  Copyright (C) 2014, 2015, 2016, 2017 Peter Johansson
8
9  This file is part of the yat library, http://dev.thep.lu.se/yat
10
11  The yat library is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 3 of the
14  License, or (at your option) any later version.
15
16  The yat library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20
21  You should have received a copy of the GNU General Public License
22  along with yat. If not, see <http://www.gnu.org/licenses/>.
23*/
24
25#include <yat/utility/DataWeight.h>
26#include <yat/utility/DataWeightProxy.h>
27
28#include <boost/iterator/iterator_archetypes.hpp>
29#include <boost/iterator/iterator_concepts.hpp>
30#include <boost/iterator/iterator_facade.hpp>
31
32namespace theplu {
33namespace yat {
34namespace utility {
35
36  /**
37     argument constructors of weighted_iterator_archetype when not
38     default constructible.
39  */
40  // Could have been a class inside of weighted_iterator_archetype,
41  // but we don't want it to be templatized.
42  struct WeightedIteratorArchetype_ctor_arg {};
43
44  // Some private aux classes for weighted_iterator_archetype
45  /// \cond IGNORE_DOXYGEN
46  namespace detail {
47  namespace weighted_iterator_archetype {
48    struct bogus {};
49
50    // Classes calculating the reference type
51
52    // default, not implemented
53    template<class AccessCategory> struct Reference {};
54
55    // readable iterators return const data weight proxy
56    template<>
57    struct Reference<boost::iterator_archetypes::readable_iterator_t>
58    {
59      typedef const utility::DataWeightProxy<const double*, const double*> type;
60    };
61
62
63    // readable_writable iterators return mutable data weight proxy
64    template<>
65    struct Reference<boost::iterator_archetypes::readable_writable_iterator_t>
66    {
67      typedef utility::DataWeightProxy<double*, double*> type;
68    };
69
70
71    // Classes defining difference type based on traversal category
72
73    // Default no difference type defined
74    template<class TraversalCategory> struct Difference {};
75
76    // If traversal is at least forward traversal, int is returned,
77    // otherwise a bogus class is returned.
78
79    template<>
80    struct Difference<boost::incrementable_traversal_tag>
81    { typedef bogus type; };
82
83    template<>
84    struct Difference<boost::single_pass_traversal_tag>
85    { typedef bogus type; };
86
87    template<>
88    struct Difference<boost::forward_traversal_tag>
89    { typedef int type; };
90
91    template<>
92    struct Difference<boost::bidirectional_traversal_tag>
93    { typedef int type; };
94
95    template<>
96    struct Difference<boost::random_access_traversal_tag>
97    { typedef int type; };
98
99  } // end of namespace weighted_iterator_archetype
100  } // end of namespace detail
101  /// \endcond
102
103  /**
104    The purpose of this class is to complement
105    boost::iterator_archetype, which doesn't work well when the
106    value_type is DataWeight (weighted iterator) and reference is not
107    DataWeight&. In that case boost::iterator_archetype creates a
108    proxy class that doesn't work well with yat's machinery to detect
109    whether an iterator is weighted or not. This class returns
110    DataWeightProxy from operator* and works as intended.
111
112    Template arguments:
113
114    AccessCategory: either
115    boost::iterator_archetypes::readable_iterator_t
116    (for const iterator) or
117    boost::iterator_archetypes::readable_writable_iterator_t
118    (for mutable iterator)
119
120    Only writable iterators are not allowed because a weighted
121    iterator must be readable in order to ensure that value_type is
122    defined.
123
124    TraversalCategory is one of the boost categories:
125    boost::single_pass_traversal_tag
126    boost::forward_traversal_tag
127    boost::bidirectional_traversal_tag
128    boost::random_access_traversal_tag
129
130    \since New in yat 0.14
131   */
132  template<typename AccessCategory, typename TraversalCategory>
133  class WeightedIteratorArchetype
134    : public boost::iterator_facade<
135    WeightedIteratorArchetype<AccessCategory, TraversalCategory>
136    , DataWeight
137    , TraversalCategory
138    , typename detail::weighted_iterator_archetype::Reference<AccessCategory>::type
139    , typename detail::weighted_iterator_archetype::Difference<TraversalCategory>::type>
140  {
141    typedef WeightedIteratorArchetype<AccessCategory, TraversalCategory> me;
142  public:
143    /**
144       \brief Default Constructor
145
146       Only implemented for single pass iterators (not for e.g. output
147       iterator).
148    */
149    WeightedIteratorArchetype(void) { is_single_pass(TraversalCategory()); }
150
151    /**
152       \brief Constructor
153
154       If iterator is not default constructible (e.g. output
155       iterator), this is only way to create an iterator.
156     */
157    explicit
158    WeightedIteratorArchetype(WeightedIteratorArchetype_ctor_arg arg)
159    {
160    }
161
162    /**
163       Create an iterator from a mutable iterator, i.e., this is a
164       copy constructor if mutable, otherwise conversion from
165       mutable to const iterator.
166    */
167    WeightedIteratorArchetype(const WeightedIteratorArchetype<boost::iterator_archetypes::readable_writable_iterator_t, TraversalCategory>& other)
168    {}
169
170  private:
171    friend class boost::iterator_core_access;
172
173    typename detail::weighted_iterator_archetype::Reference<AccessCategory>::type
174    dereference(void) const
175    { return typename detail::weighted_iterator_archetype::Reference<AccessCategory>::type(NULL, NULL); }
176
177    // operator== is only defined if single_pass
178    bool equal(const me& other) const
179    { is_single_pass(TraversalCategory()); return true; }
180
181    // increment always defined
182    void increment(void) {}
183
184    // only for bidirectional iterators
185    void decrement(void)
186    { is_bidirectional(TraversalCategory()); }
187
188    // only for random access
189    int distance_to(const me& other) const
190    { is_random(TraversalCategory()); return 0; }
191
192    // only for random access
193    void advance(int) { is_random(TraversalCategory()); }
194
195    void is_single_pass(boost::single_pass_traversal_tag) const {}
196    void is_forward(boost::forward_traversal_tag) const {}
197    void is_bidirectional(boost::bidirectional_traversal_tag) const {}
198    void is_random(boost::random_access_traversal_tag) const {}
199  };
200
201}}}
202#endif // end namspace theplu yat and utility
Note: See TracBrowser for help on using the repository browser.