Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:38:11

0001 // Copyright 2019 Hans Dembinski
0002 //
0003 // Distributed under the Boost Software License, Version 1.0.
0004 // (See accompanying file LICENSE_1_0.txt
0005 // or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Uses code segments from boost/iterator/iterator_adaptor.hpp
0008 // and boost/iterator/iterator_fascade.hpp
0009 
0010 #ifndef BOOST_HISTOGRAM_DETAIL_ITERATOR_ADAPTOR_HPP
0011 #define BOOST_HISTOGRAM_DETAIL_ITERATOR_ADAPTOR_HPP
0012 
0013 #include <cstddef>
0014 #include <iterator>
0015 #include <memory>
0016 #include <type_traits>
0017 #include <utility>
0018 
0019 namespace boost {
0020 namespace histogram {
0021 namespace detail {
0022 
0023 // operator->() needs special support for input iterators to strictly meet the
0024 // standard's requirements. If *i is not a reference type, we must still
0025 // produce an lvalue to which a pointer can be formed.  We do that by
0026 // returning a proxy object containing an instance of the reference object.
0027 template <class Reference>
0028 struct operator_arrow_dispatch_t {
0029   struct pointer {
0030     explicit pointer(Reference const& x) noexcept : m_ref(x) {}
0031     Reference* operator->() noexcept { return std::addressof(m_ref); }
0032     Reference m_ref;
0033   };
0034 
0035   using result_type = pointer;
0036   static result_type apply(Reference const& x) noexcept { return pointer(x); }
0037 };
0038 
0039 // specialization for "real" references
0040 template <class T>
0041 struct operator_arrow_dispatch_t<T&> {
0042   using result_type = T*;
0043   static result_type apply(T& x) noexcept { return std::addressof(x); }
0044 };
0045 
0046 // it is ok if void_t is already defined in another header
0047 template <class...>
0048 using void_t = void;
0049 
0050 template <class T, class = void>
0051 struct get_difference_type_impl : std::make_signed<T> {};
0052 
0053 template <class T>
0054 struct get_difference_type_impl<
0055     T, void_t<typename std::iterator_traits<T>::difference_type>> {
0056   using type = typename std::iterator_traits<T>::difference_type;
0057 };
0058 
0059 template <class T>
0060 using get_difference_type = typename get_difference_type_impl<T>::type;
0061 
0062 // adaptor supports only random access Base
0063 // Base: underlying base type of the iterator; can be iterator, pointer, integer
0064 // Reference: type returned when pointer is dereferenced
0065 template <class Derived, class Base, class Reference = std::remove_pointer_t<Base>&,
0066           class Value = std::decay_t<Reference>>
0067 class iterator_adaptor {
0068   using operator_arrow_dispatch = operator_arrow_dispatch_t<Reference>;
0069 
0070 public:
0071   using base_type = Base;
0072 
0073   using reference = Reference;
0074   using value_type = Value;
0075   using pointer = typename operator_arrow_dispatch::result_type;
0076   using difference_type = get_difference_type<base_type>;
0077   using iterator_category = std::random_access_iterator_tag;
0078 
0079   iterator_adaptor() = default;
0080 
0081   explicit iterator_adaptor(base_type const& iter) : iter_(iter) {}
0082 
0083   // you can override this in derived
0084   decltype(auto) operator*() const noexcept { return *iter_; }
0085 
0086   // you can override this in derived
0087   Derived& operator+=(difference_type n) {
0088     iter_ += n;
0089     return this->derived();
0090   }
0091 
0092   // you should override this in derived if there is an override for operator+=
0093   template <class... Ts>
0094   difference_type operator-(const iterator_adaptor<Ts...>& x) const noexcept {
0095     return iter_ - x.iter_;
0096   }
0097 
0098   // you can override this in derived
0099   template <class... Ts>
0100   bool operator==(const iterator_adaptor<Ts...>& x) const noexcept {
0101     return iter_ == x.iter_;
0102   }
0103 
0104   reference operator[](difference_type n) const { return *(this->derived() + n); }
0105   pointer operator->() const noexcept {
0106     return operator_arrow_dispatch::apply(this->derived().operator*());
0107   }
0108 
0109   Derived& operator-=(difference_type n) { return this->derived().operator+=(-n); }
0110   Derived& operator++() { return this->derived().operator+=(1); }
0111   Derived& operator--() { return this->derived().operator+=(-1); }
0112 
0113   Derived operator++(int) {
0114     Derived tmp(this->derived());
0115     operator++();
0116     return tmp;
0117   }
0118 
0119   Derived operator--(int) {
0120     Derived tmp(this->derived());
0121     operator--();
0122     return tmp;
0123   }
0124 
0125   Derived operator+(difference_type n) const { return Derived(this->derived()) += n; }
0126   Derived operator-(difference_type n) const { return Derived(this->derived()) -= n; }
0127 
0128   template <class... Ts>
0129   bool operator!=(const iterator_adaptor<Ts...>& x) const noexcept {
0130     return !this->derived().operator==(x);
0131   }
0132 
0133   template <class... Ts>
0134   bool operator<(const iterator_adaptor<Ts...>& x) const noexcept {
0135     return iter_ < x.iter_;
0136   }
0137 
0138   template <class... Ts>
0139   bool operator>=(const iterator_adaptor<Ts...>& x) const noexcept {
0140     return iter_ >= x.iter_;
0141   }
0142 
0143   template <class... Ts>
0144   bool operator>(const iterator_adaptor<Ts...>& x) const noexcept {
0145     return iter_ > x.iter_;
0146   }
0147 
0148   template <class... Ts>
0149   bool operator<=(const iterator_adaptor<Ts...>& x) const noexcept {
0150     return iter_ <= x.iter_;
0151   }
0152 
0153   friend Derived operator+(difference_type n, const Derived& x) { return x + n; }
0154 
0155   Base const& base() const noexcept { return iter_; }
0156 
0157 protected:
0158   // for convenience: refer to base class in derived class
0159   using iterator_adaptor_ = iterator_adaptor;
0160 
0161 private:
0162   Derived& derived() noexcept { return *static_cast<Derived*>(this); }
0163   const Derived& derived() const noexcept { return *static_cast<Derived const*>(this); }
0164 
0165   base_type iter_;
0166 
0167   template <class, class, class, class>
0168   friend class iterator_adaptor;
0169 };
0170 
0171 } // namespace detail
0172 } // namespace histogram
0173 } // namespace boost
0174 
0175 #endif