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();
}
|