38# include <initializer_list>
41# include <type_traits>
44# include <boost/iterator.hpp>
45# include <boost/iterator/iterator_facade.hpp>
56 using subspan_t = std::pair<std::ptrdiff_t, gsl::span<T>>;
60 :
public boost::iterator_facade<mulspan_iterator<T>, T,
61 std::bidirectional_iterator_tag> {
75 typename gsl::span<T>::iterator p)
78 , pos_cache(cached_iterator{r, p}) {}
93 auto recalculate_cache() const ->
void {
96 pos_cache = {parent->spans.begin(),
97 parent->spans.front().second.begin()};
98 }
else if (index == parent->size()) {
100 = {parent->spans.end(), parent->spans.back().second.begin()};
101 }
else if (
auto it = std::prev(parent->spans.end());
102 index >= it->first) {
103 pos_cache = {it, it->second.begin() + (index - it->first)};
106 it = std::prev(std::upper_bound(
107 parent->spans.begin(), parent->spans.end(), index,
108 [](std::ptrdiff_t l,
const subspan_t<T>& r) {
112 pos_cache = {it, it->second.begin() + (index - it->first)};
116 auto dereference() const noexcept -> T& {
118 assert(index != parent->size());
119 return *pos_cache.value().pos;
121 template <
typename U,
122 typename =
decltype(std::declval<T*>() == std::declval<U*>())>
123 auto equal(
const mulspan_iterator<U>& o)
const noexcept ->
bool {
131 std::tie(parent, index) == std::tie(o.parent, o.index);
133 auto increment() noexcept ->
void {
136 ++pos_cache.value().pos;
137 if (pos_cache.value().pos == pos_cache.value().subs->second.end()) {
138 ++pos_cache.value().subs;
139 pos_cache.value().pos = pos_cache.value().subs->second.begin();
143 auto decrement() noexcept ->
void {
146 if (pos_cache.value().pos
147 == pos_cache.value().subs->second.begin()) {
148 --pos_cache.value().subs;
149 pos_cache.value().pos = pos_cache.value().subs->second.end();
151 --pos_cache.value().pos;
155 auto advance(std::ptrdiff_t delta)
noexcept ->
void {
157 pos_cache = std::nullopt;
160 template <
typename U,
161 typename =
decltype(std::declval<T*>() == std::declval<U*>())>
162 auto distance_to(mulspan_iterator<U> o)
const noexcept -> std::ptrdiff_t {
163 return index - o.index;
167 std::ptrdiff_t index{};
168 struct cached_iterator {
169 typename std::vector<multi_impl::subspan_t<T>>::const_iterator subs;
170 typename gsl::span<T>::iterator pos;
171 auto operator==(
const cached_iterator& o)
const noexcept ->
bool {
172 return std::tie(subs, pos) == std::tie(o.subs, o.pos);
175 mutable std::optional<cached_iterator> pos_cache = std::nullopt;
198 template <
typename U,
202 : spans{{0, o}, {o.size(), {}}} {}
203 template <
typename U,
206 multi_span(std::initializer_list<gsl::span<U>> i_spans)
noexcept {
209 [
this](
int c, gsl::span<U> s) {
210 spans.push_back({c, s});
213 spans.push_back({c, {}});
215 template <
typename Iterator,
217 decltype(*std::declval<Iterator>()), gsl::span<T>>>>
220 [
this](
int c, gsl::span<T> s) {
221 spans.push_back({c, s});
224 spans.push_back({c, {}});
227 template <
typename U,
249 return {*
this,
size(), spans.end(), spans.back().second.begin()};
252 return {*
this,
size(), spans.end(), spans.back().second.begin()};
255 return {*
this,
size(), spans.end(), spans.back().second.begin()};
259 return iterator{*
this,
size(), spans.end(), spans.back().second.begin()};
262 return iterator{*
this,
size(), spans.end(), spans.back().second.begin()};
265 return iterator{*
this,
size(), spans.end(), spans.back().second.begin()};
284 return spans.back().first;
287 return spans.back().first == 0;
290 auto diag(std::ostream& os)
const noexcept ->
void {
291 os <<
"Diagnostics: " << spans.size() <<
'\n';
292 for (
auto& s : spans) {
293 os << &s <<
'\t' << s.first <<
':' << s.second.size() <<
'\t';
294 os << s.second.data() <<
',' << s.second.data() + s.second.size()
315 template <
typename U>
318 std::vector<multi_impl::subspan_t<T>> spans;
mulspan_iterator(mulspan_iterator< U > &&)
mulspan_iterator(const mulspan_iterator< U > &)
friend class multi_span< T >
mulspan_iterator(const multi_span< T > &s, std::ptrdiff_t i)
mulspan_iterator(const multi_span< T > &s)
friend class boost::iterator_core_access
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
multi_span(gsl::span< U > o) noexcept
auto crend() const noexcept -> const_reverse_iterator
multi_span(std::initializer_list< gsl::span< U > > i_spans) noexcept
std::reverse_iterator< iterator > reverse_iterator
multi_span(multi_span &&) noexcept=default
auto diag(std::ostream &os) const noexcept -> void
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
std::pair< std::ptrdiff_t, gsl::span< T > > subspan_t
The main namespace in which all entities from kblib are defined.
constexpr auto size(const C &c) -> decltype(c.size())
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.