File: shadow_iterator.hpp

package info (click to toggle)
boost1.62 1.62.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 686,420 kB
  • sloc: cpp: 2,609,004; xml: 972,558; ansic: 53,674; python: 32,437; sh: 8,829; asm: 3,071; cs: 2,121; makefile: 964; perl: 859; yacc: 472; php: 132; ruby: 94; f90: 55; sql: 13; csh: 6
file content (139 lines) | stat: -rw-r--r-- 5,040 bytes parent folder | download | duplicates (17)
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
// (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