liuxiaolong
2021-07-20 58d904a328c0d849769b483e901a0be9426b8209
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
// (C) Copyright Jeremy Siek 2001.
// Distributed under 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)
 
#ifndef BOOST_SHADOW_ITERATOR_HPP
#define BOOST_SHADOW_ITERATOR_HPP
 
#include <boost/iterator_adaptors.hpp>
#include <boost/operators.hpp>
 
namespace boost
{
 
namespace detail
{
 
    template < class A, class B, class D >
    class shadow_proxy : boost::operators< shadow_proxy< A, B, D > >
    {
        typedef shadow_proxy self;
 
    public:
        inline shadow_proxy(A aa, B bb) : a(aa), b(bb) {}
        inline shadow_proxy(const self& x) : a(x.a), b(x.b) {}
        template < class Self > inline shadow_proxy(Self x) : a(x.a), b(x.b) {}
        inline self& operator=(const self& x)
        {
            a = x.a;
            b = x.b;
            return *this;
        }
        inline self& operator++()
        {
            ++a;
            return *this;
        }
        inline self& operator--()
        {
            --a;
            return *this;
        }
        inline self& operator+=(const self& x)
        {
            a += x.a;
            return *this;
        }
        inline self& operator-=(const self& x)
        {
            a -= x.a;
            return *this;
        }
        inline self& operator*=(const self& x)
        {
            a *= x.a;
            return *this;
        }
        inline self& operator/=(const self& x)
        {
            a /= x.a;
            return *this;
        }
        inline self& operator%=(const self& x) { return *this; } // JGS
        inline self& operator&=(const self& x) { return *this; } // JGS
        inline self& operator|=(const self& x) { return *this; } // JGS
        inline self& operator^=(const self& x) { return *this; } // JGS
        inline friend D operator-(const self& x, const self& y)
        {
            return x.a - y.a;
        }
        inline bool operator==(const self& x) const { return a == x.a; }
        inline bool operator<(const self& x) const { return a < x.a; }
        //  protected:
        A a;
        B b;
    };
 
    struct shadow_iterator_policies
    {
        template < typename iter_pair > void initialize(const iter_pair&) {}
 
        template < typename Iter >
        typename Iter::reference dereference(const Iter& i) const
        {
            typedef typename Iter::reference R;
            return R(*i.base().first, *i.base().second);
        }
        template < typename Iter >
        bool equal(const Iter& p1, const Iter& p2) const
        {
            return p1.base().first == p2.base().first;
        }
        template < typename Iter > void increment(Iter& i)
        {
            ++i.base().first;
            ++i.base().second;
        }
 
        template < typename Iter > void decrement(Iter& i)
        {
            --i.base().first;
            --i.base().second;
        }
 
        template < typename Iter > bool less(const Iter& x, const Iter& y) const
        {
            return x.base().first < y.base().first;
        }
        template < typename Iter >
        typename Iter::difference_type distance(
            const Iter& x, const Iter& y) const
        {
            return y.base().first - x.base().first;
        }
        template < typename D, typename Iter > void advance(Iter& p, D n)
        {
            p.base().first += n;
            p.base().second += n;
        }
    };
 
} // namespace detail
 
template < typename IterA, typename IterB > struct shadow_iterator_generator
{
 
    // To use the iterator_adaptor we can't derive from
    // random_access_iterator because we don't have a real reference.
    // However, we want the STL algorithms to treat the shadow
    // iterator like a random access iterator.
    struct shadow_iterator_tag : public std::input_iterator_tag
    {
        operator std::random_access_iterator_tag()
        {
            return std::random_access_iterator_tag();
        };
    };
    typedef typename std::iterator_traits< IterA >::value_type Aval;
    typedef typename std::iterator_traits< IterB >::value_type Bval;
    typedef typename std::iterator_traits< IterA >::reference Aref;
    typedef typename std::iterator_traits< IterB >::reference Bref;
    typedef typename std::iterator_traits< IterA >::difference_type D;
    typedef detail::shadow_proxy< Aval, Bval, Aval > V;
    typedef detail::shadow_proxy< Aref, Bref, Aval > R;
    typedef iterator_adaptor< std::pair< IterA, IterB >,
        detail::shadow_iterator_policies, V, R, V*, shadow_iterator_tag, D >
        type;
};
 
// short cut for creating a shadow iterator
template < class IterA, class IterB >
inline typename shadow_iterator_generator< IterA, IterB >::type
make_shadow_iter(IterA a, IterB b)
{
    typedef typename shadow_iterator_generator< IterA, IterB >::type Iter;
    return Iter(std::make_pair(a, b));
}
 
template < class Cmp > struct shadow_cmp
{
    inline shadow_cmp(const Cmp& c) : cmp(c) {}
    template < class ShadowProxy1, class ShadowProxy2 >
    inline bool operator()(const ShadowProxy1& x, const ShadowProxy2& y) const
    {
        return cmp(x.a, y.a);
    }
    Cmp cmp;
};
 
} // namespace boost
 
namespace std
{
template < class A1, class B1, class D1, class A2, class B2, class D2 >
void swap(boost::detail::shadow_proxy< A1&, B1&, D1 > x,
    boost::detail::shadow_proxy< A2&, B2&, D2 > y)
{
    std::swap(x.a, y.a);
    std::swap(x.b, y.b);
}
}
 
#endif // BOOST_SHADOW_ITERATOR_HPP