32 #ifndef KBLIB_ITERATORS_H
33 #define KBLIB_ITERATORS_H
49 template <
typename ptr>
51 constexpr
auto operator()(ptr&& p)
const noexcept ->
auto {
54 constexpr
auto operator()(
const ptr& p)
const noexcept ->
auto {
61 constexpr
auto operator()(T* p)
const noexcept -> T* {
return p; }
75 template <
typename Container,
76 typename Comp = std::less<value_type_linear_t<Container>>>
78 auto it =
max_element(std::begin(c), std::end(c), comp);
79 if (it != std::end(c)) {
89 template <
typename T,
typename E,
typename =
void>
92 template <
typename T,
typename E>
94 T, E,
void_t<decltype(*std::declval<T&>()++ = std::declval<const E&>())>>
97 template <
typename Container>
162 return a.count == b.count;
167 return a.count != b.count;
172 return a.count < b.count;
177 return a.count <= b.count;
182 return a.count > b.count;
187 return a.count >= b.count;
192 return std::ptrdiff_t(
a.count) - ptrdiff_t(b.count);
201 template <
typename C>
203 C& c, std::size_t count = 0) {
220 template <
typename Value,
typename Delta>
226 constexpr
static bool nothrow_copyable
227 = std::is_nothrow_copy_constructible<Value>::value;
228 constexpr
static bool nothrow_steppable = noexcept(
min + step);
239 constexpr
range_t(Value min_, Value max_, Delta step_ = 1)
252 :
range_t(Value{}, max_, (max_ >= Value{}) ? 1 : -1) {}
273 constexpr
auto operator*() const noexcept(nothrow_copyable) -> Value {
311 return l.val == r.val and l.step == r.step;
321 return l.val != r.val or l.step != r.step;
331 return l.val < r.val;
333 return l.val > r.val;
364 constexpr
auto operator[](std::ptrdiff_t x)
const noexcept -> Value {
365 return static_cast<Value
>(
val + x *
step);
367 template <
typename Integral>
368 constexpr
auto operator[](Integral x)
const noexcept -> Value {
369 return static_cast<Value
>(
val + std::ptrdiff_t(x) *
step);
385 constexpr
auto size() const noexcept ->
std::
size_t {
386 return static_cast<std::size_t
>(std::abs(
max -
min) / step);
393 return {r.min, r.
step};
399 return {r.max, r.
step};
405 friend constexpr
auto size(
const range_t& r) noexcept -> std::size_t {
406 return (r.max - r.min) / r.step;
412 constexpr
auto empty() const noexcept ->
bool {
return size() == 0; }
414 template <
typename Integral>
416 -> decltype(
begin()[x]) {
420 constexpr
auto lesser() const noexcept(nothrow_copyable) -> Value {
421 return (step > 0) ?
max :
min;
424 constexpr
auto greater() const noexcept(nothrow_copyable) -> Value {
425 return (step > 0) ?
min :
max;
434 is_linear_container_v<
435 Container> and std::is_constructible<Container, iterator, iterator>::value>* =
nullptr>
436 explicit operator Container() const
437 noexcept(noexcept(Container(
std::declval<
iterator>(),
449 Container> and std::is_constructible<Container, iterator, iterator>::value>* =
nullptr>
450 explicit operator Container() const
451 noexcept(noexcept(Container(
std::declval<
iterator>(),
462 return (l.empty() and r.empty())
463 or ((l.begin() == r.begin()) and (l.end() == r.end())
464 and (l.step == r.step));
476 template <
typename T>
481 template <
typename T>
482 static constexpr enable_if_t<std::is_signed<T>::value,
bool> positive(T v) {
485 template <
typename R,
typename T,
486 enable_if_t<std::is_integral<R>::value
487 and std::is_integral<T>::value>* =
nullptr>
488 static constexpr
auto signed_cast(T v) {
489 return kblib::signed_cast<R>(v);
491 template <
typename R,
typename T,
493 and std::is_integral<T>::value)>* =
nullptr>
494 static constexpr
auto signed_cast(T v) {
498 constexpr
auto normalize() noexcept(nothrow_steppable) ->
void {
500 }
else if (step == 0) {
507 #pragma GCC diagnostic push
508 #pragma GCC diagnostic ignored "-Wsign-conversion"
509 #pragma GCC diagnostic ignored "-Wconversion"
510 #pragma GCC diagnostic ignored "-Wsign-compare"
511 #pragma GCC diagnostic ignored "-Wimplicit-int-conversion"
512 #pragma GCC diagnostic ignored "-Wshorten-64-to-32"
513 auto difference =
max -
min;
514 std::ptrdiff_t sign = (step > 0) ? 1 : -1;
515 if ((sign *
to_signed(difference)) <= (sign * step)) {
519 auto remainder = difference % step;
520 if (remainder != 0) {
522 assert(not (positive(max)
523 and (signed_cast<Delta>(
529 #pragma GCC diagnostic pop
534 namespace detail_iterators {
535 template <
typename T,
typename U,
typename =
void>
538 template <
typename T,
typename U>
540 void_t<decltype(
std::declval<T&>() + std::declval<U&>())>>
548 constexpr
operator std::ptrdiff_t() const noexcept {
return adj; }
551 template <
typename T>
554 decltype(std::advance(val,
a.adj))> {
555 return std::advance(val,
a.adj);
565 constexpr
operator int() const noexcept {
return 1; }
570 template <
typename T>
579 template <
typename T>
591 constexpr
operator int() const noexcept {
return -1; }
595 template <
typename T>
604 template <
typename T>
619 template <
typename Value,
typename Delta =
int>
640 template <
typename Value>
647 template <
typename Value,
typename Delta>
654 = std::is_nothrow_copy_constructible<Value>::value;
658 template <
typename Value,
typename Delta =
int>
659 constexpr
auto irange(Value, Value, Delta = 0) {}
661 template <
typename T>
662 class enumerator_iterator;
667 namespace detail_enumerate {
669 template <
typename T1,
typename T2>
670 auto get_or(T1&& t1, T2&& t2) -> decltype(
auto) {
671 return t1 ? *t1 : *t2;
677 template <
typename T>
679 static const char enumeration_magic_pointer =
'\0';
680 return reinterpret_cast<T*
>(
681 const_cast<char*
>(&enumeration_magic_pointer));
686 template <
typename T>
694 assert(other.source or other.local);
695 assert(other.source != detail_enumerate::get_magic_ptr<T>());
713 auto index() const noexcept ->
std::
size_t {
return idx; }
715 auto copied() & noexcept -> std::remove_const_t<T>& {
716 assert(source != detail_enumerate::get_magic_ptr<T>());
720 auto copied() const& noexcept -> const T& {
721 assert(source != detail_enumerate::get_magic_ptr<T>());
726 assert(source != detail_enumerate::get_magic_ptr<T>());
729 auto reffed() const& noexcept -> const T& {
730 assert(source != detail_enumerate::get_magic_ptr<T>());
735 auto set(T* t) & ->
void { source = t; }
737 auto advance() & noexcept ->
void {
739 source = detail_enumerate::get_magic_ptr<T>();
740 local = std::nullopt;
744 mutable std::optional<std::remove_const_t<T>> local = std::nullopt;
745 T* source = detail_enumerate::get_magic_ptr<T>();
753 # if defined(__clang__)
755 # pragma clang diagnostic push
756 # pragma clang diagnostic ignored "-Wmismatched-tags"
759 template <
typename T>
761 :
public std::integral_constant<std::size_t, 2> {};
763 template <
typename T>
768 template <
typename T>
773 template <
typename T>
776 using type =
const std::size_t;
782 template <
typename T>
790 template <
typename T>
798 template <
typename T>
801 using type = std::remove_const_t<T>;
806 template <
typename T>
812 # if defined(__clang__)
813 # pragma clang diagnostic pop
823 template <std::
size_t I,
typename T>
825 static_assert(I <= 1,
"enumeration only has two elements");
826 if constexpr (I == 0) {
832 template <std::
size_t I,
typename T>
834 static_assert(I <= 1,
"enumeration only has two elements");
835 if constexpr (I == 0) {
843 template <std::
size_t I,
typename T>
845 static_assert(I <= 1,
"enumeration only has two elements");
846 if constexpr (I == 0) {
853 template <std::
size_t I,
typename T>
855 static_assert(I <= 1,
"enumeration only has two elements");
856 if constexpr (I == 0) {
863 template <
typename It>
868 typename std::iterator_traits<It>::value_type>;
879 other.curr_.idx, other.it_) {}
905 return lhs.it_ == rhs.it_;
909 return lhs.it_ != rhs.it_;
919 bool captured =
false;
923 template <
typename Range,
typename =
void>
926 template <
typename Range>
931 using range_t =
typename std::remove_reference_t<Range>;
953 template <
typename It,
typename EndIt>
987 template <
typename It,
typename EIt>
1012 template <
typename Range>
1014 if constexpr (std::is_lvalue_reference_v<Range&&>) {
1028 template <
typename Iter1,
typename Iter2>
1036 constexpr
auto end() const noexcept -> Iter2 {
return end_; }
1037 constexpr
auto rbegin() const noexcept -> auto {
1038 return std::make_reverse_iterator(
begin_);
1040 constexpr
auto rend() const noexcept -> auto {
1041 return std::make_reverse_iterator(
end_);
1058 template <
typename Iter1,
typename Iter2>
1059 constexpr
auto indirect(Iter1 begin, Iter2 end) noexcept(noexcept(
1061 return {begin, end};
1066 template <
typename Iter1,
typename Iter2>
1069 template <
typename Iter1,
typename Iter2>
1077 template <
typename Iter1,
typename EndIter = Iter1, std::
size_t count = 0>
1086 std::array<range, count> ranges;
1090 template <
typename Iter1,
typename EndIter>
1099 std::vector<range> ranges;
1107 template <
typename T>
1130 constexpr
auto get() noexcept -> T* {
return &
val; }
1134 constexpr
auto get() const noexcept -> const T* {
return &
val; }
1147 template <
typename base_iterator,
typename operation>
1157 = decltype(
kblib::invoke(std::as_const(op), *std::as_const(it)));
1171 operation _op) noexcept(noexcept(base_iterator{
1172 _it}) and noexcept(std::is_nothrow_move_constructible<operation>::value))
1200 decltype(
auto) operator*() const noexcept(noexcept(
kblib::
invoke(op, *it))) {
1231 [[deprecated(
"Needlessly copies op. Use preincrement instead.")]]
auto
1237 auto base() const noexcept -> base_iterator {
return it; }
1244 return lhs.it == rhs.it;
1252 return lhs.it != rhs.it;
1255 template <
typename OIt>
1257 const OIt& rhs) noexcept ->
bool {
1258 return lhs.base() == rhs;
1260 template <
typename OIt>
1263 return lhs == rhs.base();
1266 template <
typename OIt>
1268 const OIt& rhs) noexcept ->
bool {
1269 return lhs.base() != rhs;
1271 template <
typename OIt>
1274 return lhs != rhs.base();
1278 template <
typename It,
typename operation>
1290 template <
typename base_iterator,
typename operation>
1295 it, std::move(op)})) -> transform_iterator<base_iterator, operation> {
1296 return {it, std::move(op)};
1306 template <
typename base_iterator,
typename operation>
1309 -> transform_iterator<base_iterator, operation> {
1310 return {it, std::move(op)};
1313 template <
typename It,
typename EndIt,
typename operation>
1320 template <
typename InputIt1,
typename EndIt,
typename InputIt2>
1327 = std::is_nothrow_copy_constructible<InputIt1>::value
1328 and std::is_nothrow_copy_constructible<EndIt>::value
1329 and std::is_nothrow_copy_constructible<InputIt2>::value;
1346 return std::forward_as_tuple(*
pos1, *
pos2);
1354 noexcept(
std::is_nothrow_copy_constructible<EndIt>::value and
1355 std::is_nothrow_copy_constructible<InputIt2>::value)
1362 const zip_iterator& z2) noexcept(noexcept(z1.pos1 == z2.pos1)) ->
bool {
1363 return z1.pos1 == z2.pos1;
1367 const zip_iterator& z2) noexcept(noexcept(z1.pos1 != z2.pos1)) ->
bool {
1368 return z1.pos1 != z2.pos1;
1375 return z1.end1 ==
end.val;
1382 return z1.end1 !=
end.val;
1386 template <
typename It1,
typename It2>
1393 = std::is_nothrow_copy_constructible<It1>::value
1394 and std::is_nothrow_copy_constructible<It2>::value;
1410 return std::forward_as_tuple(*
pos1, *
pos2);
1418 noexcept(
std::is_nothrow_copy_constructible<It1>::value)
1425 const zip_iterator& z2) noexcept(noexcept(z1.pos1 == z2.pos1)) ->
bool {
1426 return z1.pos1 == z2.pos1;
1430 const zip_iterator& z2) noexcept(noexcept(z1.pos1 == z2.pos1)) ->
bool {
1431 return z1.pos1 != z2.pos1;
1446 template <
typename InputIt1,
typename EndIt,
typename InputIt2>
1450 return {begin1, end1, begin2};
1462 template <
typename Range1,
typename Range2>
1465 decltype(begin(r2))>::is_nothrow_copyable)
1466 ->
zip_iterator<decltype(begin(r1)), decltype(end(r1)),
1467 decltype(begin(r2))> {
1468 return {begin(r1), end(r1), begin(r2)};
1472 template <
typename ForwardIt,
typename EndIt>
1492 template <
typename Container,
typename F>
1511 template <
typename V>
1520 container.push_back(
invoke(fun, std::forward<V>(value)));
1534 Container& container;
1542 template <
typename F>
1568 template <
typename V>
1598 template <
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.
std::output_iterator_tag iterator_category
consume_iterator(F f)
Constructs a consume_iterator with the given function object.
auto operator=(V &&value) noexcept(noexcept(kblib::invoke(fun, std::forward< V >(value)))) -> consume_iterator &
Pass value to F.
auto operator++(int) -> consume_iterator &
A no-op.
auto operator++() -> consume_iterator &
A no-op.
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
enumeration< nested_value > value_type
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
constexpr static bool nothrow_steppable
constexpr static bool nothrow_copyable
A range generator, similar to Python 3's range().
constexpr auto operator[](Integral x) const noexcept -> decltype(begin()[x])
constexpr friend 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.
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 friend auto size(const range_t &r) noexcept -> std::size_t
Returns the distance between start() and stop().
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.
constexpr friend auto end(const range_t &r) noexcept -> iterator
Return an iterator to the end of the range.
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 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 magic_enumerate(It begin, EIt end) -> enumerator_t< It, EIt >
Allow access to indexes while using range-based for loops.
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 zip(InputIt1 begin1, EndIt end1, InputIt2 begin2) noexcept(zip_iterator< InputIt1, EndIt, InputIt2 >::is_nothrow_copyable) -> zip_iterator< InputIt1, EndIt, InputIt2 >
Iterate over two ranges in lockstep, like Python's zip.
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.
typename std::enable_if< B, T >::type enable_if_t
constexpr auto operator+(T val, adjuster a) noexcept -> enable_if_t< not detail_iterators::is_addable< T, std::ptrdiff_t >::value, decltype(std::advance(val, a.adj))>
auto cry_enumerate(Range &&range) -> auto
constexpr auto range(Value min, Value max, Delta step=0) -> range_t< Value, Delta >
Constructs a range from beginning, end, and step amount. The range is half-open, that is min is in th...
constexpr auto irange(Value, Value, Delta=0)
counting_back_insert_iterator< C > counting_back_inserter(C &c, std::size_t count=0)
constexpr auto max_element(ForwardIt first, EndIt last, Compare comp={}) -> ForwardIt
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.
auto get(punner< Types... > &p) noexcept -> decltype(auto)
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 >
typename value_type_linear< Container >::type value_type_linear_t
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.
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.
constexpr friend 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 friend auto operator*(std::ptrdiff_t x, incrementer)
constexpr incrementer() noexcept=default
constexpr auto operator()(T &t) -> T &
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 &
constexpr static bool is_nothrow_copyable
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.