summaryrefslogtreecommitdiff
path: root/boost/range/adaptor/indexed.hpp
blob: 5a523cec583b0bc4e5bed863078df910a11a2416 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// Boost.Range library
//
//  Copyright Thorsten Ottosen, Neil Groves 2006 - 2008. Use, modification and
//  distribution is subject to the Boost Software License, Version
//  1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//

#ifndef BOOST_RANGE_ADAPTOR_INDEXED_IMPL_HPP
#define BOOST_RANGE_ADAPTOR_INDEXED_IMPL_HPP

#include <boost/config.hpp>
#ifdef BOOST_MSVC
#pragma warning( push )
#pragma warning( disable : 4355 )
#endif

#include <boost/range/adaptor/argument_fwd.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/iterator/iterator_adaptor.hpp>



namespace boost
{
    namespace adaptors
    {
        // This structure exists to carry the parameters from the '|' operator
        // to the index adapter. The expression rng | indexed(1) instantiates
        // this structure and passes it as the right-hand operand to the
        // '|' operator.
        struct indexed
        {
            explicit indexed(std::size_t x) : val(x) {}
            std::size_t val;
        };
    }

    namespace range_detail
    {
        template< class Iter >
        class indexed_iterator
            : public boost::iterator_adaptor< indexed_iterator<Iter>, Iter >
        {
        private:
            typedef boost::iterator_adaptor< indexed_iterator<Iter>, Iter >
                  base;

            typedef BOOST_DEDUCED_TYPENAME base::difference_type index_type;

            index_type m_index;

        public:
            explicit indexed_iterator( Iter i, index_type index )
            : base(i), m_index(index)
            {
                BOOST_ASSERT( m_index >= 0 && "Indexed Iterator out of bounds" );
            }

            index_type index() const
            {
                return m_index;
            }

         private:
            friend class boost::iterator_core_access;

            void increment()
            {
                ++m_index;
                ++(this->base_reference());
            }


            void decrement()
            {
                BOOST_ASSERT( m_index > 0 && "Indexed Iterator out of bounds" );
                --m_index;
                --(this->base_reference());
            }

            void advance( index_type n )
            {
                m_index += n;
                BOOST_ASSERT( m_index >= 0 && "Indexed Iterator out of bounds" );
                this->base_reference() += n;
            }
        };

        template< class Rng >
        struct indexed_range :
            iterator_range< indexed_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type> >
        {
        private:
            typedef indexed_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type>
                iter_type;
            typedef iterator_range<iter_type>
                base;
        public:
            template< class Index >
            indexed_range( Index i, Rng& r )
              : base( iter_type(boost::begin(r), i), iter_type(boost::end(r),i) )
            { }
        };

    } // 'range_detail'

    // Make this available to users of this library. It will sometimes be
    // required since it is the return type of operator '|' and
    // index().
    using range_detail::indexed_range;

    namespace adaptors
    {
        template< class SinglePassRange >
        inline indexed_range<SinglePassRange>
        operator|( SinglePassRange& r,
                   const indexed& f )
        {
            return indexed_range<SinglePassRange>( f.val, r );
        }

        template< class SinglePassRange >
        inline indexed_range<const SinglePassRange>
        operator|( const SinglePassRange& r,
                   const indexed& f )
        {
            return indexed_range<const SinglePassRange>( f.val, r );
        }

        template<class SinglePassRange, class Index>
        inline indexed_range<SinglePassRange>
        index(SinglePassRange& rng, Index index_value)
        {
            return indexed_range<SinglePassRange>(index_value, rng);
        }

        template<class SinglePassRange, class Index>
        inline indexed_range<const SinglePassRange>
        index(const SinglePassRange& rng, Index index_value)
        {
            return indexed_range<const SinglePassRange>(index_value, rng);
        }
    } // 'adaptors'

}

#ifdef BOOST_MSVC
#pragma warning( pop )
#endif

#endif