source: branches/0.14-stable/yat/utility/WeightedIteratorArchetype.h @ 3569

Last change on this file since 3569 was 3569, checked in by Peter, 6 years ago

std::iterator_traits<T>::value_type does not work on OSX when T is an
incrementable iterator (not single pass). As this must work for an
iterator that models concept Data Iterator, add single pass iterator
as an requirement, test for it in the concept check class (plus a few
more fixes) and turn off the test in
'test/weighted_iterator_archetype.cc'.

  • 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 3569 2017-01-09 03:43:08Z 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.