43# include <type_traits>
46# include <boost/iterator.hpp>
47# include <boost/iterator/iterator_facade.hpp>
48# if __cpp_lib_span >= 202002L
55# if __cpp_lib_span >= 202002L
68 using subspan_t = std::pair<std::ptrdiff_t, span<T>>;
72 :
public boost::iterator_facade<mulspan_iterator<T>, T,
73 std::bidirectional_iterator_tag> {
87 typename span<T>::iterator p)
90 , pos_cache(cached_iterator{r, p}) {}
103 friend class boost::iterator_core_access;
105 auto recalculate_cache() const ->
void {
108 pos_cache = {parent->spans.begin(),
109 parent->spans.front().second.begin()};
110 }
else if (index == parent->size()) {
112 = {parent->spans.end(), parent->spans.back().second.begin()};
113 }
else if (
auto it = std::prev(parent->spans.end());
114 index >= it->first) {
115 pos_cache = {it, it->second.begin() + (index - it->first)};
118 it = std::prev(std::upper_bound(
119 parent->spans.begin(), parent->spans.end(), index,
120 [](std::ptrdiff_t l,
const subspan_t<T>& r) {
124 pos_cache = {it, it->second.begin() + (index - it->first)};
128 auto dereference() const noexcept -> T& {
130 assert(index != parent->size());
131 return *pos_cache.value().pos;
133 template <
typename U,
134 typename =
decltype(std::declval<T*>() == std::declval<U*>())>
135 auto equal(
const mulspan_iterator<U>& o)
const noexcept ->
bool {
143 std::tie(parent, index) == std::tie(o.parent, o.index);
145 auto increment() noexcept ->
void {
148 ++pos_cache.value().pos;
149 if (pos_cache.value().pos == pos_cache.value().subs->second.end()) {
150 ++pos_cache.value().subs;
151 pos_cache.value().pos = pos_cache.value().subs->second.begin();
155 auto decrement() noexcept ->
void {
158 if (pos_cache.value().pos
159 == pos_cache.value().subs->second.begin()) {
160 --pos_cache.value().subs;
161 pos_cache.value().pos = pos_cache.value().subs->second.end();
163 --pos_cache.value().pos;
167 auto advance(std::ptrdiff_t delta)
noexcept ->
void {
169 pos_cache = std::nullopt;
172 template <
typename U,
173 typename =
decltype(std::declval<T*>() == std::declval<U*>())>
174 auto distance_to(mulspan_iterator<U> o)
const noexcept -> std::ptrdiff_t {
175 return index - o.index;
178 const multi_span<T>* parent{};
179 std::ptrdiff_t index{};
180 struct cached_iterator {
181 typename std::vector<multi_impl::subspan_t<T>>::const_iterator subs;
182 typename span<T>::iterator pos;
183 auto operator==(
const cached_iterator& o)
const noexcept ->
bool {
184 return std::tie(subs, pos) == std::tie(o.subs, o.pos);
187 mutable std::optional<cached_iterator> pos_cache = std::nullopt;
210 template <
typename U,
214 : spans{{0, o}, {o.size(), {}}} {}
215 template <
typename U,
218 multi_span(std::initializer_list<span<U>> i_spans)
noexcept {
221 spans.push_back({c, s});
224 spans.push_back({c, {}});
226 template <
typename Iterator,
228 decltype(*std::declval<Iterator>()), span<T>>>>
231 [
this](
int c, span<T> s) {
232 spans.push_back({c, s});
235 spans.push_back({c, {}});
238 template <
typename U,
260 return {*
this,
size(), spans.end(), spans.back().second.begin()};
263 return {*
this,
size(), spans.end(), spans.back().second.begin()};
266 return {*
this,
size(), spans.end(), spans.back().second.begin()};
270 return iterator{*
this,
size(), spans.end(), spans.back().second.begin()};
273 return iterator{*
this,
size(), spans.end(), spans.back().second.begin()};
276 return iterator{*
this,
size(), spans.end(), spans.back().second.begin()};
295 return spans.back().first;
298 return spans.back().first == 0;
301 auto diag(std::ostream& os)
const noexcept ->
void {
302 os <<
"Diagnostics: " << spans.size() <<
'\n';
303 for (
auto& s : spans) {
304 os << &s <<
'\t' << s.first <<
':' << s.second.size() <<
'\t';
305 os << s.second.data() <<
',' << s.second.data() + s.second.size()
326 template <
typename U>
329 std::vector<multi_impl::subspan_t<T>> spans;
mulspan_iterator(mulspan_iterator< U > &&)
mulspan_iterator(const mulspan_iterator< U > &)
mulspan_iterator(const multi_span< T > &s, std::ptrdiff_t i)
mulspan_iterator(const multi_span< T > &s)
mulspan_iterator()=default
auto cend() const noexcept -> const_iterator
auto rbegin() noexcept -> reverse_iterator
auto crbegin() const noexcept -> const_reverse_iterator
auto end() noexcept -> iterator
auto begin() const noexcept -> const_iterator
multi_span(Iterator begin, Iterator end) noexcept
multi_span(const multi_span &)=default
auto crend() const noexcept -> const_reverse_iterator
multi_span(span< U > o) noexcept
std::reverse_iterator< iterator > reverse_iterator
multi_span(multi_span &&) noexcept=default
auto diag(std::ostream &os) const noexcept -> void
multi_span(std::initializer_list< span< U > > i_spans) noexcept
multi_span(const multi_span< U > &)
auto cbegin() const noexcept -> const_iterator
auto rend() noexcept -> reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
std::ptrdiff_t difference_type
reference operator[](index_type i) const
auto end() const noexcept -> const_iterator
std::remove_cv< T > value_type
auto size() const noexcept -> index_type
auto rend() const noexcept -> const_reverse_iterator
auto rbegin() const noexcept -> const_reverse_iterator
auto empty() const noexcept -> bool
std::ptrdiff_t index_type
constexpr auto size(const C &c) -> decltype(c.size())
std::pair< std::ptrdiff_t, span< T > > subspan_t
typename std::enable_if< B, T >::type enable_if_t
constexpr auto accumulate(InputIt first, InputIt last, T init) -> T
A constexpr version of std::accumulate.
constexpr auto equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) -> bool
Provides macros and basic templates used by the rest of kblib.
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.