yat/utility/WeightedIteratorArchetype.h

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