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>
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);
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 {
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>(),
450 Container> and std::is_constructible<Container, iterator, iterator>::value>* =
nullptr>
451 explicit operator Container() const
452 noexcept(noexcept(Container(
std::declval<
iterator>(),
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>
489 static constexpr auto signed_cast(T v) {
490 return kblib::signed_cast<R>(v);
492 template <
typename R,
typename T,
494 and std::is_integral<T>::value)>* =
nullptr>
495 static constexpr auto signed_cast(T v) {
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>
655 = std::is_nothrow_copy_constructible<Value>::value;
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>
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>
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; }
1245 return lhs.it == rhs.it;
1253 return lhs.it != rhs.it;
1256 template <
typename OIt>
1258 const OIt& rhs)
noexcept ->
bool {
1259 return lhs.base() == rhs;
1261 template <
typename OIt>
1264 return lhs == rhs.base();
1267 template <
typename OIt>
1269 const OIt& rhs)
noexcept ->
bool {
1270 return lhs.base() != rhs;
1272 template <
typename OIt>
1275 return lhs != rhs.base();
1279template <
typename It,
typename operation>
1291template <
typename base_iterator,
typename operation>
1296 it, std::move(op)})) -> transform_iterator<base_iterator, operation> {
1297 return {it, std::move(op)};
1307template <
typename base_iterator,
typename operation>
1310 -> transform_iterator<base_iterator, operation> {
1311 return {it, std::move(op)};
1314template <
typename It,
typename EndIt,
typename operation>
1321template <
typename InputIt1,
typename EndIt,
typename InputIt2>
1328 = std::is_nothrow_copy_constructible<InputIt1>::value
1329 and std::is_nothrow_copy_constructible<EndIt>::value
1330 and std::is_nothrow_copy_constructible<InputIt2>::value;
1347 return std::forward_as_tuple(*
pos1, *
pos2);
1355 noexcept(
std::is_nothrow_copy_constructible<EndIt>::value and
1356 std::is_nothrow_copy_constructible<InputIt2>::value)
1363 const zip_iterator& z2)
noexcept(
noexcept(z1.pos1 == z2.pos1)) ->
bool {
1364 return z1.pos1 == z2.pos1;
1368 const zip_iterator& z2)
noexcept(
noexcept(z1.pos1 != z2.pos1)) ->
bool {
1369 return z1.pos1 != z2.pos1;
1376 return z1.end1 ==
end.val;
1383 return z1.end1 !=
end.val;
1387template <
typename It1,
typename It2>
1394 = std::is_nothrow_copy_constructible<It1>::value
1395 and std::is_nothrow_copy_constructible<It2>::value;
1411 return std::forward_as_tuple(*
pos1, *
pos2);
1419 noexcept(
std::is_nothrow_copy_constructible<It1>::value)
1426 const zip_iterator& z2)
noexcept(
noexcept(z1.pos1 == z2.pos1)) ->
bool {
1427 return z1.pos1 == z2.pos1;
1431 const zip_iterator& z2)
noexcept(
noexcept(z1.pos1 == z2.pos1)) ->
bool {
1432 return z1.pos1 != z2.pos1;
1447template <
typename InputIt1,
typename EndIt,
typename InputIt2>
1451 return {begin1, end1, begin2};
1463template <
typename Range1,
typename Range2>
1466 decltype(begin(r2))>::is_nothrow_copyable)
1467 ->
zip_iterator<
decltype(begin(r1)),
decltype(end(r1)),
1468 decltype(begin(r2))> {
1469 return {begin(r1), end(r1), begin(r2)};
1473template <
typename ForwardIt,
typename EndIt>
1493template <
typename Container,
typename F>
1512 template <
typename V>
1521 container.push_back(
invoke(fun, std::forward<V>(value)));
1535 Container& container;
1543template <
typename F>
1575 template <
typename V>
1607template <
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
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
static constexpr bool nothrow_copyable
static constexpr bool nothrow_steppable
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 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
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)
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)
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.
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
static constexpr bool is_nothrow_copyable
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.