32#ifndef KBLIB_ITERATORS_H
33#define KBLIB_ITERATORS_H
50template <
typename ptr>
52 constexpr auto operator()(ptr&& p)
const noexcept ->
auto {
55 constexpr auto operator()(
const ptr& p)
const noexcept ->
auto {
62 constexpr auto operator()(T* p)
const noexcept -> T* {
return p; }
76template <
typename Container,
77 typename Comp = std::less<value_type_linear_t<Container>>>
79 auto it =
max_element(std::begin(c), std::end(c), comp);
80 if (it != std::end(c)) {
90template <
typename T,
typename E,
typename =
void>
93template <
typename T,
typename E>
95 T, E,
void_t<decltype(*std::declval<T&>()++ = std::declval<const E&>())>>
98template <
typename Container>
117 : container(
std::addressof(c))
130 container->push_back(value);
139 container->push_back(std::move(value));
149 return {container, &dirty};
163 return a.count == b.count;
168 return a.count != b.count;
173 return a.count < b.count;
178 return a.count <= b.count;
183 return a.count > b.count;
188 return a.count >= b.count;
193 return std::ptrdiff_t(
a.count) - ptrdiff_t(b.count);
197 Container* container =
nullptr;
198 std::size_t count = 0;
204 C& c, std::size_t count = 0) {
221template <
typename Value,
typename Delta>
227 constexpr static bool nothrow_copyable
228 = std::is_nothrow_copy_constructible<Value>::value;
229 constexpr static bool nothrow_steppable =
noexcept(
min + step);
240 constexpr range_t(Value min_, Value max_, Delta step_ = 1)
253 :
range_t(Value{}, max_, (max_ >= Value{}) ? 1 : -1) {}
274 constexpr auto operator*() const noexcept(nothrow_copyable) -> Value {
290 val =
static_cast<Value
>(val + step);
312 return l.val == r.val and l.step == r.step;
322 return l.val != r.val or l.step != r.step;
332 return l.val < r.val;
334 return l.val > r.val;
365 constexpr auto operator[](std::ptrdiff_t x)
const noexcept -> Value {
366 return static_cast<Value
>(val + x * step);
368 template <
typename Integral>
369 constexpr auto operator[](Integral x)
const noexcept -> Value {
370 return static_cast<Value
>(val + std::ptrdiff_t(x) * step);
386 constexpr auto size() const noexcept ->
std::
size_t {
387 return static_cast<std::size_t
>(std::abs(
max -
min) / step);
394 return {r.min, r.
step};
400 return {r.max, r.
step};
406 friend constexpr auto size(
const range_t& r)
noexcept -> std::size_t {
407 return (r.max - r.min) / r.step;
413 constexpr auto empty() const noexcept ->
bool {
return size() == 0; }
415 template <
typename Integral>
417 ->
decltype(begin()[x]) {
421 constexpr auto lesser() const noexcept(nothrow_copyable) -> Value {
422 return (step > 0) ?
max :
min;
425 constexpr auto greater() const noexcept(nothrow_copyable) -> Value {
426 return (step > 0) ?
min :
max;
435 is_linear_container_v<
436 Container> and std::is_constructible<Container, iterator, iterator>::value>* =
nullptr>
437 explicit operator Container() const
438 noexcept(noexcept(Container(
std::declval<
iterator>(),
440 return Container(begin(), end());
450 Container> and std::is_constructible<Container, iterator, iterator>::value>* =
nullptr>
451 explicit operator Container() const
452 noexcept(noexcept(Container(
std::declval<
iterator>(),
454 return Container(begin(), end());
463 return (l.empty() and r.empty())
464 or ((l.begin() == r.begin()) and (l.end() == r.end())
465 and (l.step == r.step));
477 template <
typename T>
482 template <
typename T>
483 static constexpr enable_if_t<std::is_signed<T>::value,
bool> positive(T v) {
486 template <
typename R,
typename T,
487 enable_if_t<std::is_integral<R>::value
488 and std::is_integral<T>::value>* =
nullptr>
490 return kblib::signed_cast<R>(v);
492 template <
typename R,
typename T,
494 and std::is_integral<T>::value)>* =
nullptr>
499 constexpr auto normalize() noexcept(nothrow_steppable) ->
void {
501 }
else if (step == 0) {
508#pragma GCC diagnostic push
509#pragma GCC diagnostic ignored "-Wsign-conversion"
510#pragma GCC diagnostic ignored "-Wconversion"
511#pragma GCC diagnostic ignored "-Wsign-compare"
512#pragma GCC diagnostic ignored "-Wimplicit-int-conversion"
513#pragma GCC diagnostic ignored "-Wshorten-64-to-32"
514 auto difference =
max -
min;
515 std::ptrdiff_t sign = (step > 0) ? 1 : -1;
516 if ((sign *
to_signed(difference)) <= (sign * step)) {
520 auto remainder = difference % step;
521 if (remainder != 0) {
523 assert(not (positive(
max)
524 and (signed_cast<Delta>(
530#pragma GCC diagnostic pop
535namespace detail_iterators {
536 template <
typename T,
typename U,
typename =
void>
539 template <
typename T,
typename U>
541 void_t<decltype(
std::declval<T&>() + std::declval<U&>())>>
549 constexpr operator std::ptrdiff_t() const noexcept {
return adj; }
555 decltype(std::advance(val,
a.adj))> {
556 return std::advance(val,
a.adj);
566 constexpr operator int() const noexcept {
return 1; }
571 template <
typename T>
592 constexpr operator int() const noexcept {
return -1; }
596 template <
typename T>
620template <
typename Value,
typename Delta =
int>
641template <
typename Value>
648template <
typename Value,
typename Delta>
654 constexpr static bool nothrow_copyable
655 = std::is_nothrow_copy_constructible<Value>::value;
656 constexpr static bool nothrow_steppable =
noexcept(
min + step);
659template <
typename Value,
typename Delta =
int>
660constexpr auto irange(Value, Value, Delta = 0) {}
663class enumerator_iterator;
668namespace detail_enumerate {
670 template <
typename T1,
typename T2>
671 auto get_or(T1&& t1, T2&& t2) ->
decltype(
auto) {
672 return t1 ? *t1 : *t2;
678 template <
typename T>
680 static const char enumeration_magic_pointer =
'\0';
681 return reinterpret_cast<T*
>(
682 const_cast<char*
>(&enumeration_magic_pointer));
695 assert(other.source or other.local);
696 assert(other.source != detail_enumerate::get_magic_ptr<T>());
714 auto index() const noexcept ->
std::
size_t {
return idx; }
716 auto copied() &
noexcept -> std::remove_const_t<T>& {
717 assert(source != detail_enumerate::get_magic_ptr<T>());
721 auto copied() const& noexcept -> const T& {
722 assert(source != detail_enumerate::get_magic_ptr<T>());
727 assert(source != detail_enumerate::get_magic_ptr<T>());
730 auto reffed() const& noexcept -> const T& {
731 assert(source != detail_enumerate::get_magic_ptr<T>());
736 auto set(T* t) & ->
void { source = t; }
738 auto advance() &
noexcept ->
void {
740 source = detail_enumerate::get_magic_ptr<T>();
741 local = std::nullopt;
745 mutable std::optional<std::remove_const_t<T>> local = std::nullopt;
746 T* source = detail_enumerate::get_magic_ptr<T>();
754# if defined(__clang__)
756# pragma clang diagnostic push
757# pragma clang diagnostic ignored "-Wmismatched-tags"
762 :
public std::integral_constant<std::size_t, 2> {};
777 using type =
const std::size_t;
802 using type = std::remove_const_t<T>;
813# if defined(__clang__)
814# pragma clang diagnostic pop
824template <std::
size_t I,
typename T>
826 static_assert(I <= 1,
"enumeration only has two elements");
827 if constexpr (I == 0) {
833template <std::
size_t I,
typename T>
835 static_assert(I <= 1,
"enumeration only has two elements");
836 if constexpr (I == 0) {
844template <std::
size_t I,
typename T>
846 static_assert(I <= 1,
"enumeration only has two elements");
847 if constexpr (I == 0) {
854template <std::
size_t I,
typename T>
856 static_assert(I <= 1,
"enumeration only has two elements");
857 if constexpr (I == 0) {
864template <
typename It>
869 typename std::iterator_traits<It>::value_type>;
880 other.curr_.idx, other.it_) {}
906 return lhs.it_ == rhs.it_;
910 return lhs.it_ != rhs.it_;
920 bool captured =
false;
924template <
typename Range,
typename =
void>
927template <
typename Range>
932 using range_t =
typename std::remove_reference_t<Range>;
954template <
typename It,
typename EndIt>
988template <
typename It,
typename EIt>
1013template <
typename Range>
1015 if constexpr (std::is_lvalue_reference_v<Range&&>) {
1029template <
typename Iter1,
typename Iter2>
1036 constexpr auto begin() const noexcept -> Iter1 {
return begin_; }
1037 constexpr auto end() const noexcept -> Iter2 {
return end_; }
1038 constexpr auto rbegin() const noexcept -> auto {
1039 return std::make_reverse_iterator(begin_);
1041 constexpr auto rend() const noexcept -> auto {
1042 return std::make_reverse_iterator(end_);
1059template <
typename Iter1,
typename Iter2>
1060constexpr auto indirect(Iter1 begin, Iter2 end)
noexcept(
noexcept(
1062 return {begin, end};
1067template <
typename Iter1,
typename Iter2>
1070template <
typename Iter1,
typename Iter2>
1078template <
typename Iter1,
typename EndIter = Iter1, std::
size_t count = 0>
1087 std::array<range, count> ranges;
1091template <
typename Iter1,
typename EndIter>
1100 std::vector<range> ranges;
1108template <
typename T>
1117 constexpr auto operator*() const noexcept -> const T& {
return val; }
1126 constexpr auto operator->() const noexcept -> const T* {
return &val; }
1131 constexpr auto get() noexcept -> T* {
return &val; }
1135 constexpr auto get() const noexcept -> const T* {
return &val; }
1148template <
typename base_iterator,
typename operation>
1158 =
decltype(
kblib::invoke(std::as_const(op), *std::as_const(it)));
1172 operation _op)
noexcept(
noexcept(base_iterator{
1173 _it}) and
noexcept(std::is_nothrow_move_constructible<operation>::value))
1175 , op(std::move(_op)) {}
1232 [[deprecated(
"Needlessly copies op. Use preincrement instead.")]]
auto
1238 auto base() const noexcept -> base_iterator {
return it; }
1241 noexcept(std::is_nothrow_copy_constructible_v<operation>)
1251 return lhs.it == rhs.it;
1259 return lhs.it != rhs.it;
1262 template <
typename OIt>
1264 const OIt& rhs)
noexcept ->
bool {
1265 return lhs.base() == rhs;
1267 template <
typename OIt>
1270 return lhs == rhs.base();
1273 template <
typename OIt>
1275 const OIt& rhs)
noexcept ->
bool {
1276 return lhs.base() != rhs;
1278 template <
typename OIt>
1281 return lhs != rhs.base();
1285template <
typename It,
typename operation>
1297template <
typename base_iterator,
typename operation>
1302 it, std::move(op)})) -> transform_iterator<base_iterator, operation> {
1303 return {it, std::move(op)};
1313template <
typename base_iterator,
typename operation>
1316 -> transform_iterator<base_iterator, operation> {
1317 return {it, std::move(op)};
1320template <
typename It,
typename EndIt,
typename operation>
1327template <
typename InputIt1,
typename EndIt,
typename InputIt2>
1333 constexpr static bool is_nothrow_copyable
1334 = std::is_nothrow_copy_constructible<InputIt1>::value
1335 and std::is_nothrow_copy_constructible<EndIt>::value
1336 and std::is_nothrow_copy_constructible<InputIt2>::value;
1338 auto operator++() noexcept(noexcept(++pos1) and noexcept(++pos2))
1353 return std::forward_as_tuple(*pos1, *pos2);
1361 noexcept(
std::is_nothrow_copy_constructible<EndIt>::value and
1362 std::is_nothrow_copy_constructible<InputIt2>::value)
1364 return {end1, end1};
1369 const zip_iterator& z2)
noexcept(
noexcept(z1.pos1 == z2.pos1)) ->
bool {
1370 return z1.pos1 == z2.pos1;
1374 const zip_iterator& z2)
noexcept(
noexcept(z1.pos1 != z2.pos1)) ->
bool {
1375 return z1.pos1 != z2.pos1;
1382 return z1.end1 == end.val;
1389 return z1.end1 != end.val;
1393template <
typename It1,
typename It2>
1399 constexpr static bool is_nothrow_copyable
1400 = std::is_nothrow_copy_constructible<It1>::value
1401 and std::is_nothrow_copy_constructible<It2>::value;
1408 auto operator++(
int)
noexcept(is_nothrow_copyable and
noexcept(++pos1))
1417 return std::forward_as_tuple(*pos1, *pos2);
1425 noexcept(
std::is_nothrow_copy_constructible<It1>::value)
1427 return {end1, end1, pos2};
1432 const zip_iterator& z2)
noexcept(
noexcept(z1.pos1 == z2.pos1)) ->
bool {
1433 return z1.pos1 == z2.pos1;
1437 const zip_iterator& z2)
noexcept(
noexcept(z1.pos1 == z2.pos1)) ->
bool {
1438 return z1.pos1 != z2.pos1;
1453template <
typename InputIt1,
typename EndIt,
typename InputIt2>
1457 return {begin1, end1, begin2};
1469template <
typename Range1,
typename Range2>
1472 decltype(begin(r2))>::is_nothrow_copyable)
1473 ->
zip_iterator<
decltype(begin(r1)),
decltype(end(r1)),
1474 decltype(begin(r2))> {
1475 return {begin(r1), end(r1), begin(r2)};
1479template <
typename ForwardIt,
typename EndIt>
1499template <
typename Container,
typename F>
1518 template <
typename V>
1527 container.push_back(
invoke(fun, std::forward<V>(value)));
1541 Container& container;
1549template <
typename F>
1581 template <
typename V>
1613template <
typename F>
TODO(killerbee13): Implement adjacent_iterator.
std::input_iterator_tag iterator_category
std::ptrdiff_t difference_type
std::pair< base_reference, base_reference > value_type
typename std::iterator_traits< ForwardIt >::reference base_reference
An OutputIterator that transforms the values assigned to it before inserting them into the back of a ...
std::output_iterator_tag iterator_category
auto operator*() -> back_insert_iterator_F &
A no-op.
auto operator=(V &&value) -> back_insert_iterator_F &
Calls container.push_back(kblib::invoke(fun, std::forward<V>(value)));.
back_insert_iterator_F(Container &c, F f)
auto operator++() -> back_insert_iterator_F &
A no-op.
An OutputIterator that simply calls a provided functor for each value assigned to it.
consume_iterator(const consume_iterator &)=default
std::output_iterator_tag iterator_category
auto operator=(const consume_iterator &) &-> consume_iterator &=default
consume_iterator(F f)
Constructs a consume_iterator with the given function object.
~consume_iterator()=default
auto operator=(V &&value) noexcept(noexcept(kblib::invoke(fun, std::forward< V >(value)))) -> kblib::ignore_t< decltype(kblib::invoke(fun, std::forward< V >(value))), consume_iterator & >
Pass value to F.
auto operator++(int) -> consume_iterator &
A no-op.
consume_iterator(consume_iterator &&)=default
auto operator++() -> consume_iterator &
A no-op.
auto operator=(consume_iterator &&) &-> consume_iterator &=default
auto operator*() -> consume_iterator &
A no-op.
Like a std::back_insert_iterator, but it keeps track of how many insertions it has made,...
friend auto operator>=(const counting_back_insert_iterator &a, const counting_back_insert_iterator &b) noexcept -> bool
friend auto operator==(const counting_back_insert_iterator &a, const counting_back_insert_iterator &b) noexcept -> bool
std::ptrdiff_t difference_type
auto operator++(int) noexcept -> counting_back_insert_iterator=delete
friend auto operator-(const counting_back_insert_iterator &a, const counting_back_insert_iterator &b) noexcept -> std::ptrdiff_t
friend auto operator<(const counting_back_insert_iterator &a, const counting_back_insert_iterator &b) noexcept -> bool
friend auto operator>(const counting_back_insert_iterator &a, const counting_back_insert_iterator &b) noexcept -> bool
auto operator++() &noexcept -> counting_back_insert_iterator &
friend auto operator!=(const counting_back_insert_iterator &a, const counting_back_insert_iterator &b) noexcept -> bool
counting_back_insert_iterator() noexcept=default
auto operator*() noexcept -> proxy_iterator
counting_back_insert_iterator(std::size_t n)
std::output_iterator_tag iterator_category
friend auto operator<=(const counting_back_insert_iterator &a, const counting_back_insert_iterator &b) noexcept -> bool
auto operator=(const enumeration &)=delete
auto copied() &noexcept -> std::remove_const_t< T > &
auto operator=(enumeration &&)=delete
auto reffed() &noexcept -> T &
auto index() const noexcept -> std::size_t
enumeration(volatile enumeration &other)
auto copied() const &noexcept -> const T &
auto reffed() const &noexcept -> const T &
enumeration(const enumeration &other)
enumeration(enumeration &&)=delete
enumerator_iterator(const enumerator_iterator &other)
~enumerator_iterator()=default
auto operator++() &-> enumerator_iterator &
enumerator_iterator()=default
auto operator=(enumerator_iterator &&) -> enumerator_iterator &=default
friend auto operator==(const enumerator_iterator &lhs, const enumerator_iterator &rhs) noexcept -> bool
std::input_iterator_tag iterator_category
auto operator=(const enumerator_iterator &) -> enumerator_iterator &=default
enumerator_iterator(It it)
std::ptrdiff_t difference_type
copy_const_t< decltype(*std::declval< It & >()), typename std::iterator_traits< It >::value_type > nested_value
auto operator*() &-> volatile value_type &
enumerator_iterator(enumerator_iterator &&)=default
friend auto operator!=(const enumerator_iterator &lhs, const enumerator_iterator &rhs) noexcept -> bool
typename range_t::const_iterator nested_const_iterator
auto end() &noexcept(noexcept(r.end())) -> end_iterator
typename std::remove_reference_t< Range > range_t
decltype(r.begin()) nested_iterator
auto begin() const &noexcept(noexcept(r.cbegin())) -> const_iterator
auto begin() &noexcept(noexcept(r.begin())) -> iterator
decltype(r.end()) nested_end_iterator
detail::no_dangle_t< Range > r
auto end() const &noexcept(noexcept(r.cend())) -> const_iterator
auto end() const &noexcept -> end_iterator
auto begin() const &noexcept -> iterator
A range generator, similar to Python 3's range().
friend constexpr auto size(const range_t &r) noexcept -> std::size_t
Returns the distance between start() and stop().
constexpr auto operator[](Integral x) const noexcept -> decltype(begin()[x])
friend constexpr auto begin(const range_t &r) noexcept -> iterator
Returns an iterator to the beginning of the range.
constexpr auto lesser() const noexcept(nothrow_copyable) -> Value
constexpr auto end() const noexcept -> iterator
Return an iterator to the end of the range.
friend constexpr auto end(const range_t &r) noexcept -> iterator
Return an iterator to the end of the range.
constexpr auto empty() const noexcept -> bool
Query whether the range will generate any elements.
constexpr auto greater() const noexcept(nothrow_copyable) -> Value
constexpr auto size() const noexcept -> std::size_t
Returns the distance between start() and stop().
constexpr range_t(Value max_)
1-argument constructor. Start is implicitly zero and step is 1 or -1, depending on the sign of max.
constexpr friend auto operator==(range_t l, range_t r) noexcept -> bool
Compare l and r for equality.
constexpr friend auto operator!=(range_t l, range_t r) noexcept -> bool
Compare l and r for inequality.
constexpr auto begin() const noexcept -> iterator
Returns an iterator to the beginning of the range.
constexpr range_t(Value min_, Value max_, Delta step_=1)
2- and 3-argument constructor. Explicitly specify start, end, and optionally the step amount.
std::remove_const_t< T > type
This header provides some features of C++17 <type_traits> and other headers for C++14,...
auto get_magic_ptr() -> T *
auto get_or(T1 &&t1, T2 &&t2) -> decltype(auto)
typename no_dangle< T >::type no_dangle_t
typename make_void< Ts... >::type void_t
constexpr auto size(const C &c) -> decltype(c.size())
constexpr struct kblib::nums::min_t min
constexpr struct kblib::nums::max_t max
The main namespace in which all entities from kblib are defined.
auto transformer(base_iterator it, operation op) noexcept(noexcept(transform_iterator< base_iterator, operation >{it, std::move(op)})) -> transform_iterator< base_iterator, operation >
Factory function to make transform_iterators.
auto transform_range(It begin, EndIt end, operation op) noexcept(noexcept(indirect(transform_iterator{begin, op}, end))) -> auto
auto consumer(F f) -> consume_iterator< F >
Creates a consume_iterator of deduced type F.
constexpr auto to_signed(I x) -> std::make_signed_t< I >
Cast integral argument to corresponding signed type.
constexpr auto to_pointer(P &&p) noexcept -> auto *
Gets a raw pointer out of any smart pointer or iterator you might pass in, without dereferencing it o...
constexpr auto a(const std::initializer_list< T > &a) -> auto
Index an array literal without naming its type.
auto get(const volatile enumeration< T > &e) -> decltype(auto)
typename std::enable_if< B, T >::type enable_if_t
typename ignore< U, T >::type ignore_t
An alias for ignore<U, T>::type.
counting_back_insert_iterator< C > counting_back_inserter(C &c, std::size_t count=0)
auto magic_enumerate(Range &&r) -> auto
Allow access to indexes while using range-based for loops. Safe to use with rvalues.
constexpr auto irange(Value, Value, Delta=0)
auto cry_enumerate(Iter1 begin, Iter2 end) -> auto
auto max_element(Container &c, Comp comp) -> value_type_linear_t< Container > *
constexpr auto indirect(Iter1 begin, Iter2 end) noexcept(noexcept(indirect_range< Iter1, Iter2 >{begin, end})) -> indirect_range< Iter1, Iter2 >
Create a range from an iterator pair. Primarily useful for range-for loops.
constexpr auto invoke(F &&f, Args &&... args) noexcept(noexcept(detail::do_invoke(std::forward< F >(f), std::forward< Args >(args)...))) -> decltype(auto)
transform_iterator(It, operation) -> transform_iterator< It, operation >
constexpr auto operator+(T val, decrementer) -> T
Decrements val.
typename value_type_linear< Container >::type value_type_linear_t
constexpr auto range(Value max) -> range_t< Value, incrementer >
Constructs a half-open range [0, max). The step is automatically determined based on the sign of max.
constexpr auto signed_cast(F x) -> enable_if_t< std::is_integral< A >::value and std::is_integral< F >::value and std::is_signed< A >::value, std::make_signed_t< F > >
Cast argument to equivalently-sized type with the same signednessas the template parameter.
indirect_range(Iter1, Iter2) -> indirect_range< Iter1, Iter2 >
auto make_transform_iterator(base_iterator it, operation op) noexcept(noexcept(transform_iterator< base_iterator, operation >{ it, std::move(op)})) -> transform_iterator< base_iterator, operation >
Factory function to make transform_iterators.
auto zip(Range1 &&r1, Range2 &&r2) noexcept(zip_iterator< decltype(begin(r1)), decltype(end(r1)), decltype(begin(r2))>::is_nothrow_copyable) -> zip_iterator< decltype(begin(r1)), decltype(end(r1)), decltype(begin(r2))>
Iterate over two ranges in lockstep, like Python's zip.
typename copy_const< C, V >::type copy_const_t
constexpr adjuster(std::ptrdiff_t adj_) noexcept
A smart pointer to an object contained inside the smart pointer object.
constexpr auto operator*() const noexcept -> const T &
Returns the contained object.
constexpr auto operator->() const noexcept -> const T *
Return the address of the contained object.
constexpr auto operator->() noexcept -> T *
Return the address of the contained object.
constexpr auto get() noexcept -> T *
Returns the address of the contained object.
constexpr auto operator*() noexcept -> T &
Returns the contained object.
constexpr auto get() const noexcept -> const T *
Returns the address of the contained object.
auto operator=(value_type &&value) &-> proxy_iterator &
auto operator=(const value_type &value) &-> proxy_iterator &
typename Container::value_type value_type
A struct which decrements anything it is added to. Suitable for use as a Delta type for range_t.
friend constexpr auto operator*(std::ptrdiff_t x, decrementer)
constexpr decrementer() noexcept=default
constexpr auto operator()(T &t) -> T &
A struct which increments anything it is added to. Suitable for use as a Delta type for range_t.
constexpr incrementer() noexcept=default
constexpr auto operator()(T &t) -> T &
friend constexpr auto operator*(std::ptrdiff_t x, incrementer)
Allow range-for iteration of an iterator pair.
constexpr auto rend() const noexcept -> auto
constexpr friend auto begin(const indirect_range &r) noexcept -> Iter1
decltype(*begin_) value_type
constexpr friend auto end(const indirect_range &r) noexcept -> Iter2
constexpr auto begin() const noexcept -> Iter1
constexpr auto end() const noexcept -> Iter2
constexpr auto rbegin() const noexcept -> auto
Determine if T is a valid output iterator to which values of type E may be written.
A helper struct which acts as an iterator for the range elements, as they are generated on the fly.
constexpr friend auto operator>(iterator l, iterator r) noexcept -> bool
Compare two range iterators.
constexpr auto operator[](Integral x) const noexcept -> Value
constexpr auto operator++(int) noexcept(nothrow_steppable) -> iterator
Postfix increment. Advance to the next value in the range, but return the current value.
constexpr friend auto operator!=(iterator l, iterator r) noexcept -> bool
Compare two range iterators for inequality.
constexpr friend auto operator<(iterator l, iterator r) noexcept -> bool
Compare two range iterators.
constexpr auto operator*() const noexcept(nothrow_copyable) -> Value
Return the "pointed-to" value.
constexpr friend auto operator>=(iterator l, iterator r) noexcept -> bool
Compare two range iterators.
constexpr auto operator[](std::ptrdiff_t x) const noexcept -> Value
constexpr friend auto operator<=(iterator l, iterator r) noexcept -> bool
Compare two range iterators.
std::ptrdiff_t difference_type
constexpr auto operator++() &noexcept(nothrow_steppable) -> iterator &
Prefix increment. Advance to the next value in the range.
constexpr auto operator->() const noexcept -> pointer
Return a pointer to the value.
constexpr friend auto operator==(iterator l, iterator r) noexcept -> bool
Compare two range iterators for equality.
std::input_iterator_tag iterator_category
constexpr auto operator()(T *p) const noexcept -> T *
constexpr auto operator()(const ptr &p) const noexcept -> auto
constexpr auto operator()(ptr &&p) const noexcept -> auto
auto operator++() noexcept(noexcept(++pos1)) -> zip_iterator &
friend auto operator!=(const zip_iterator &z1, const zip_iterator &z2) noexcept(noexcept(z1.pos1==z2.pos1)) -> bool
friend auto operator==(const zip_iterator &z1, const zip_iterator &z2) noexcept(noexcept(z1.pos1==z2.pos1)) -> bool
auto begin() const noexcept(is_nothrow_copyable) -> zip_iterator
auto operator++(int) noexcept(is_nothrow_copyable and noexcept(++pos1)) -> const zip_iterator
auto end() const noexcept(std::is_nothrow_copy_constructible< It1 >::value) -> zip_iterator
auto operator++() noexcept(noexcept(++pos1) and noexcept(++pos2)) -> zip_iterator &
friend auto operator==(const zip_iterator &z1, const zip_iterator &z2) noexcept(noexcept(z1.pos1==z2.pos1)) -> bool
friend auto operator!=(const zip_iterator &z1, zip_iterator< EndIt, EndIt, InputIt2 > end) noexcept(noexcept(z1.pos1==end.val)) -> bool
friend auto operator!=(const zip_iterator &z1, const zip_iterator &z2) noexcept(noexcept(z1.pos1 !=z2.pos1)) -> bool
friend auto operator==(const zip_iterator &z1, zip_iterator< EndIt, EndIt, InputIt2 > end) noexcept(noexcept(z1.pos1==end.val)) -> bool
auto end() const noexcept(std::is_nothrow_copy_constructible< EndIt >::value and std::is_nothrow_copy_constructible< InputIt2 >::value) -> zip_iterator< EndIt, EndIt, InputIt2 >
auto begin() const noexcept(is_nothrow_copyable) -> zip_iterator
auto operator*() const noexcept -> auto
auto operator++(int) noexcept(is_nothrow_copyable and noexcept(++pos1) and noexcept(++pos2)) -> const zip_iterator
#define KBLIB_NODISCARD
This internal macro is used to provide a fallback for [[nodiscard]] in C++14.
Contains some type traits not in the standard library that are useful in the implementation of kblib.