source: trunk/test/weighted_iterator_archetype.h @ 3379

Last change on this file since 3379 was 3379, checked in by Peter, 9 years ago

avoid using weighted_iterator_archetype with incrementable_traversal_tag. note, should reflect this in docs and concept checks in library as well. refs #803

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.1 KB
Line 
1#ifndef _theplu_yat_test_weighted_iterator_archetype
2#define _theplu_yat_test_weighted_iterator_archetype
3
4// $Id: weighted_iterator_archetype.h 3379 2015-02-13 11:22:36Z peter $
5
6/*
7  Copyright (C) 2014 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 test {
35
36  // argument to iterators that are not default constructible
37  struct ctor_arg {};
38
39  // perhaps the stuff below should live in its own namespace, since
40  // no one is really expected to use these classes other than the
41  // weighted_iterator_archetype class below.
42
43  struct bogus {};
44
45  template<class AccessCategory> struct Reference {};
46
47  template<>
48  struct Reference<boost::iterator_archetypes::readable_iterator_t>
49  {
50    typedef const utility::DataWeightProxy<const double*, const double*> type;
51  };
52
53
54  template<>
55  struct Reference<boost::iterator_archetypes::readable_writable_iterator_t>
56  {
57    typedef utility::DataWeightProxy<double*, double*> type;
58  };
59
60  template<class TraversalCategory> struct Difference {};
61
62  template<>
63  struct Difference<boost::incrementable_traversal_tag>
64  { typedef bogus type; };
65
66  template<>
67  struct Difference<boost::single_pass_traversal_tag>
68  { typedef bogus type; };
69
70  template<>
71  struct Difference<boost::forward_traversal_tag>
72  { typedef int type; };
73
74  template<>
75  struct Difference<boost::bidirectional_traversal_tag>
76  { typedef int type; };
77
78  template<>
79  struct Difference<boost::random_access_traversal_tag>
80  { typedef int type; };
81
82
83  /*
84    The purpose of this class is to complement
85    boost::iterator_archetype, which doesn't work well when the
86    value_type is DataWeight (weighted iterator) and reference is not
87    DataWeight&. In that case boost::iterator_archetype creates a
88    proxy class that doesn't work well with yat's machinery to detect
89    whether an iterator is weighted or not. Instead we should use this
90    class below for testing. It returns DataWeightProxy from operator*
91    and works as intended.
92
93    Template arguments:
94
95    AccessCategory: either
96    boost::iterator_archetypes::readable_iterator_t
97    (for const iterator) or
98    boost::iterator_archetypes::readable_writable_iterator_t
99    (for mutable iterator)
100
101    Only writable iterators are not allowed because a weighted
102    iterator must be readable in order to ensure that value_type is
103    defined.
104
105    TraversalCategory is one of the boost categories:
106    // currently not working boost::incrementable_traversal_tag
107    boost::single_pass_traversal_tag
108    boost::forward_traversal_tag
109    boost::bidirectional_traversal_tag
110    boost::random_access_traversal_tag
111   */
112  template<typename AccessCategory, typename TraversalCategory>
113  class weighted_iterator_archetype
114    : public boost::iterator_facade<
115    weighted_iterator_archetype<AccessCategory, TraversalCategory>
116    , utility::DataWeight
117    , TraversalCategory
118    , typename Reference<AccessCategory>::type
119    , typename Difference<TraversalCategory>::type>
120  {
121    typedef weighted_iterator_archetype<AccessCategory, TraversalCategory> me;
122  public:
123    // constructors
124    weighted_iterator_archetype(void) { is_forward(TraversalCategory()); }
125    weighted_iterator_archetype(ctor_arg arg)
126    {
127      // Category incrementable_traversal_tag is problematic on
128      // certain systems, so avoid usage.
129      is_single_pass(TraversalCategory());
130    }
131
132    // Create an iterator from a mutable iterator, i.e., this is a
133    // copy constructor if if mutable, otherwise conversion from
134    // mutable to const iterator.
135    weighted_iterator_archetype(const weighted_iterator_archetype<boost::iterator_archetypes::readable_writable_iterator_t, TraversalCategory>& other)
136    {}
137
138  private:
139    friend class boost::iterator_core_access;
140
141    typename Reference<AccessCategory>::type
142    dereference(void) const
143    { return typename Reference<AccessCategory>::type(NULL, NULL); }
144
145    bool equal(const me& other) const
146    { is_single_pass(TraversalCategory()); return true; }
147    void increment(void) {}
148
149    // only for bidirectional iterators
150    void decrement(void)
151    { is_bidirectional(TraversalCategory()); }
152
153    // only for random access
154    int distance_to(const me& other) const
155    { is_random(TraversalCategory()); return 0; }
156
157    void advance(int) { is_random(TraversalCategory()); }
158
159    void is_single_pass(boost::single_pass_traversal_tag) const {}
160    void is_forward(boost::forward_traversal_tag) const {}
161    void is_bidirectional(boost::bidirectional_traversal_tag) const {}
162    void is_random(boost::random_access_traversal_tag) const {}
163  };
164
165}}}
166#endif
Note: See TracBrowser for help on using the repository browser.