File: detail_iterator_adaptor_test.cpp

package info (click to toggle)
boost1.88 1.88.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 576,932 kB
  • sloc: cpp: 4,149,234; xml: 136,789; ansic: 35,092; python: 33,910; asm: 5,698; sh: 4,604; ada: 1,681; makefile: 1,633; pascal: 1,139; perl: 1,124; sql: 640; yacc: 478; ruby: 271; java: 77; lisp: 24; csh: 6
file content (218 lines) | stat: -rw-r--r-- 5,995 bytes parent folder | download | duplicates (4)
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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
//  (C) Copyright Thomas Witt 2003.
//  (C) Copyright Hans Dembinski 2019.

//  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)

//  See http://www.boost.org for most recent version including documentation.

#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/histogram/detail/iterator_adaptor.hpp>
#include <deque>
#include <set>
#include <type_traits>
#include <vector>
#include "iterator.hpp"
#include "std_ostream.hpp"

using boost::histogram::detail::iterator_adaptor;

typedef std::deque<int> storage;
typedef std::deque<int*> pointer_deque;
typedef std::set<storage::iterator> iterator_set;

template <class T>
struct foo;

void blah(int) {}

struct my_gen {
  typedef int result_type;
  my_gen() : n(0) {}
  int operator()() { return ++n; }
  int n;
};

template <class V>
struct ptr_iterator : iterator_adaptor<ptr_iterator<V>, V*> {
private:
  typedef iterator_adaptor<ptr_iterator<V>, V*> super_t;

public:
  using base_type = typename super_t::base_type;

  ptr_iterator() {}
  ptr_iterator(V* d) : super_t(d) {}

  template <class V2, class = std::enable_if_t<std::is_convertible<V2*, V*>::value>>
  ptr_iterator(const ptr_iterator<V2>& x) : super_t(x.base()) {}

  V& operator*() const { return *(this->base()); }
};

template <class Iter>
struct constant_iterator
    : iterator_adaptor<constant_iterator<Iter>, Iter,
                       typename std::iterator_traits<Iter>::value_type const&> {
  typedef iterator_adaptor<constant_iterator<Iter>, Iter,
                           typename std::iterator_traits<Iter>::value_type const&>
      base_t;

  constant_iterator() {}
  constant_iterator(Iter it) : base_t(it) {}

  typename std::iterator_traits<Iter>::value_type const& operator*() const {
    this->base().operator*();
  }
};

struct mutable_it : iterator_adaptor<mutable_it, int*> {
  typedef iterator_adaptor<mutable_it, int*> super_t;

  mutable_it();
  explicit mutable_it(int* p) : super_t(p) {}

  bool equal(mutable_it const& rhs) const { return this->base() == rhs.base(); }
};

struct constant_it : iterator_adaptor<constant_it, int const*> {
  typedef iterator_adaptor<constant_it, int const*> super_t;

  constant_it();
  explicit constant_it(int* p) : super_t(p) {}
  constant_it(mutable_it const& x) : super_t(x.base()) {}

  bool equal(constant_it const& rhs) const { return this->base() == rhs.base(); }
};

template <class T>
class static_object {
public:
  static T& get() {
    static char d[sizeof(T)];
    return *reinterpret_cast<T*>(d);
  }
};

int main() {
  dummyT array[] = {dummyT(0), dummyT(1), dummyT(2), dummyT(3), dummyT(4), dummyT(5)};
  const int N = sizeof(array) / sizeof(dummyT);

  // Test the iterator_adaptor
  {
    ptr_iterator<dummyT> i(array);
    using reference = typename std::iterator_traits<ptr_iterator<dummyT>>::reference;
    using pointer = typename std::iterator_traits<ptr_iterator<dummyT>>::pointer;
    BOOST_TEST_TRAIT_SAME(reference, dummyT&);
    BOOST_TEST_TRAIT_SAME(pointer, dummyT*);

    random_access_iterator_test(i, N, array);

    ptr_iterator<const dummyT> j(array);
    random_access_iterator_test(j, N, array);
    const_nonconst_iterator_test(i, ++j);
  }

  // Test the iterator_traits
  {
    // Test computation of defaults
    typedef ptr_iterator<int> Iter1;
    // don't use std::iterator_traits here to avoid VC++ problems
    BOOST_TEST_TRAIT_SAME(Iter1::value_type, int);
    BOOST_TEST_TRAIT_SAME(Iter1::reference, int&);
    BOOST_TEST_TRAIT_SAME(Iter1::pointer, int*);
    BOOST_TEST_TRAIT_SAME(Iter1::difference_type, std::ptrdiff_t);
  }

  {
    // Test computation of default when the Value is const
    typedef ptr_iterator<int const> Iter1;
    BOOST_TEST_TRAIT_SAME(Iter1::value_type, int);
    BOOST_TEST_TRAIT_SAME(Iter1::reference, const int&);
    BOOST_TEST_TRAIT_SAME(Iter1::pointer, int const*);
  }

  {
    // Test constant iterator idiom
    typedef ptr_iterator<int> BaseIter;
    typedef constant_iterator<BaseIter> Iter;

    BOOST_TEST_TRAIT_SAME(Iter::value_type, int);
    BOOST_TEST_TRAIT_SAME(Iter::reference, int const&);
    BOOST_TEST_TRAIT_SAME(Iter::pointer, int const*);
  }

  // Test the iterator_adaptor
  {
    ptr_iterator<dummyT> i(array);
    random_access_iterator_test(i, N, array);

    ptr_iterator<const dummyT> j(array);
    random_access_iterator_test(j, N, array);
    const_nonconst_iterator_test(i, ++j);
  }

  // check that base_type is correct
  {
    // Test constant iterator idiom
    typedef ptr_iterator<int> BaseIter;

    BOOST_TEST_TRAIT_SAME(BaseIter::base_type, int*);
    BOOST_TEST_TRAIT_SAME(constant_iterator<BaseIter>::base_type, BaseIter);
  }

  {
    int data[] = {49, 77};

    mutable_it i(data);
    constant_it j(data + 1);
    BOOST_TEST(i < j);
    BOOST_TEST(j > i);
    BOOST_TEST(i <= j);
    BOOST_TEST(j >= i);
    BOOST_TEST(j - i == 1);
    BOOST_TEST(i - j == -1);

    constant_it k = i;

    BOOST_TEST(!(i < k));
    BOOST_TEST(!(k > i));
    BOOST_TEST(i <= k);
    BOOST_TEST(k >= i);
    BOOST_TEST(k - i == 0);
    BOOST_TEST(i - k == 0);
  }

  {
    using C = std::vector<int>;
    C a = {{1, 2, 3, 4}};

    struct skip_iterator : iterator_adaptor<skip_iterator, C::iterator> {
      using difference_type = typename iterator_adaptor_::difference_type;
      using iterator_adaptor_::iterator_adaptor_;

      skip_iterator& operator+=(difference_type n) {
        iterator_adaptor_::operator+=(n * 2);
        return *this;
      }
    };

    {
      skip_iterator it(a.begin());
      BOOST_TEST_EQ(it.base() - a.begin(), 0);
      BOOST_TEST_EQ(*it++, 1);
      BOOST_TEST_EQ(*it++, 3);
      BOOST_TEST_EQ(a.end() - it.base(), 0);
    }

    {
      int i = 0;
      for (auto it = skip_iterator(a.begin()); it != skip_iterator(a.end()); ++it) ++i;
      BOOST_TEST_EQ(i, 2);
    }
  }

  return boost::report_errors();
}