histogram/test/detail_iterator_adaptor_test.cpp
2019-06-08 16:28:56 +02:00

192 lines
5.2 KiB
C++

// (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/detect.hpp>
#include <boost/histogram/detail/iterator_adaptor.hpp>
#include "std_ostream.hpp"
#include "utility_iterator.hpp"
#include <deque>
#include <set>
#include <vector>
using namespace boost::histogram;
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 = detail::requires_convertible<V2*, V*>>
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);
}
return boost::report_errors();
}