File indexing completed on 2025-01-18 09:38:11
0001
0002
0003
0004
0005
0006
0007
0008
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
0024
0025
0026
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
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
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
0063
0064
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
0084 decltype(auto) operator*() const noexcept { return *iter_; }
0085
0086
0087 Derived& operator+=(difference_type n) {
0088 iter_ += n;
0089 return this->derived();
0090 }
0091
0092
0093 template <class... Ts>
0094 difference_type operator-(const iterator_adaptor<Ts...>& x) const noexcept {
0095 return iter_ - x.iter_;
0096 }
0097
0098
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
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 }
0172 }
0173 }
0174
0175 #endif