35# include <type_traits>
93 namespace stl_zip_detail
99 return (...
and (std::get<0>(
its) != std::get<1>(
its)));
106 (++std::get<0>(
its), ...);
113 return std::tuple<decltype(*std::get<0>(
its))...>(*std::get<0>(
its)...);
117 template <
typename IterPair>
118 using iter_value_t = std::decay_t<decltype(*std::get<0>(std::declval<IterPair>()))>;
150 std::pair<typename std::decay_t<Containers>::const_iterator,
151 typename std::decay_t<Containers>::const_iterator>...>;
155 typename std::decay_t<Containers>::value_type...>;
158 const typename std::decay_t<Containers>::value_type &...>;
166 template <
size_t...
Is>
173 template <
size_t...
Is>
180 template <
size_t...
Is>
187 template <
size_t...
Is>
190 return (...
and (std::get<0>(std::get<Is>(
iters_)) ==
191 std::get<1>(std::get<Is>(
iters_))));
222 return has_curr_impl(std::make_index_sequence<num_containers>{});
233 return completed_impl(std::make_index_sequence<num_containers>{});
243 return deref_impl(std::make_index_sequence<num_containers>{});
252 advance_impl(std::make_index_sequence<num_containers>{});
345 return std::apply([](
const auto &...
cs)
357 return std::apply([](
const auto &...
cs)
416 static_assert(
sizeof...(Containers) >= 2,
"stl_zip requires at least 2 containers");
474 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
475 if (
not std::forward<Pred>(
pred)(it.get_curr()))
496 for (; it.has_curr(); it.next())
497 if (
not std::forward<Pred>(
pred)(it.get_curr()))
499 return it.completed();
531 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
532 if (std::forward<Pred>(
pred)(it.get_curr()))
589 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
590 std::forward<Op>(op)(it.get_curr());
606 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
607 std::forward<Op>(op)(idx, it.get_curr());
644 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
645 acc = std::forward<Op>(op)(std::move(
acc), it.get_curr());
688 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(std::declval<TupleType>()))>;
690 std::vector<ResultType> result;
691 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
692 result.push_back(std::forward<Op>(op)(it.get_curr()));
713 std::vector<TupleType> result;
714 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
715 if (
auto t = it.get_curr(); std::forward<Pred>(
pred)(t))
735 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
736 if (
auto t = it.get_curr(); std::forward<Pred>(
pred)(t))
737 return std::optional<TupleType>(t);
738 return std::optional<TupleType>{};
755 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
756 if (std::forward<Pred>(
pred)(it.get_curr()))
774 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
792 while (it.has_curr())
794 return it.completed();
813 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++i)
815 return std::optional<TupleType>(it.get_curr());
816 return std::optional<TupleType>{};
834 std::vector<TupleType> result;
838 result.push_back(it.get_curr());
857 std::vector<TupleType> result;
861 for (
size_t i = 0; i < n
and it.has_curr(); ++i)
865 for (; it.has_curr(); it.next())
866 result.push_back(it.get_curr());
889 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
890 if (
auto t = it.get_curr(); std::forward<Pred>(
pred)(t))
916 std::vector<TupleType> result;
917 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
918 result.push_back(it.get_curr());
942 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
943 if (
not std::forward<Pred>(
pred)(it.get_curr()))
962 for (; it.has_curr(); it.next())
963 if (
not std::forward<Pred>(
pred)(it.get_curr()))
965 return it.completed();
972 namespace stl_zip_detail
975 template <
typename Cmp,
typename Tuple,
size_t...
Is>
978 return (...
and cmp(std::get<Is>(t), std::get<Is + 1>(t)));
1007 template <
typename Cmp,
typename...
Containers>
1010 static_assert(
sizeof...(Containers) >= 2,
"stl_zip_cmp requires at least 2 containers");
1012 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1014 constexpr size_t N =
sizeof...(Containers);
1015 if (
auto t = it.get_curr();
not
1038 template <
typename Container>
1044 using value_type = std::tuple<size_t, typename std::decay_t<Container>::value_type>;
1047 typename std::decay_t<Container>::const_iterator
curr_;
1048 typename std::decay_t<Container>::const_iterator
end_;
1098 template <
typename Container>
1139 template <
typename Container>
1179 std::vector<TupleType> result;
1180 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1183 if (
not std::forward<Pred>(
pred)(t))
1185 result.push_back(t);
1208 std::vector<TupleType> result;
1212 for (; it.has_curr()
and std::forward<Pred>(
pred)(it.get_curr()); it.next())
1216 for (; it.has_curr(); it.next())
1217 result.push_back(it.get_curr());
1256 std::optional<TupleType> result;
1257 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1277 std::optional<TupleType> result;
1278 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1281 if (std::forward<Pred>(
pred)(t))
1301 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
1302 if (std::forward<Pred>(
pred)(it.get_curr()))
1329 template <
typename T,
typename U>
1337 for (
const auto & [f, s]:
pairs)
1342 return std::make_pair(std::move(
firsts), std::move(
seconds));
1365 template <
typename...
Ts>
1368 std::tuple<std::vector<Ts>...> result;
1377 for (
const auto & t:
tuples)
1379 std::apply([&t](
auto &...
vecs)
1381 std::apply([&
vecs...](
const auto &...
elems)
1383 (vecs.push_back(elems), ...);
1418 template <
typename Container>
1421 using T =
typename std::decay_t<Container>::value_type;
1422 std::vector<std::pair<T, T>> result;
1424 auto it = c.begin();
1431 for (; it != c.end(); ++it)
1433 result.emplace_back(prev, *it);
1456 template <
typename Op,
typename Container>
1459 using T =
typename std::decay_t<Container>::value_type;
1460 using R = std::decay_t<decltype(std::forward<Op>(op)(std::declval<T>(), std::declval<T>()))>;
1462 std::vector<R> result;
1464 auto it = c.begin();
1471 for (; it != c.end(); ++it)
1473 result.push_back(std::forward<Op>(op)(prev, *it));
1500 template <
typename Pred,
typename Container>
1503 auto it = c.begin();
1510 for (; it != c.end(); ++it)
1512 if (
not std::forward<Pred>(
pred)(prev, *it))
1529 template <
typename Pred,
typename Container>
1532 auto it = c.begin();
1539 for (; it != c.end(); ++it)
1541 if (std::forward<Pred>(
pred)(prev, *it))
1575 using ResultType = std::decay_t<decltype(std::forward<Op>(op)(
size_t{}, std::declval<TupleType>()))>;
1577 std::vector<ResultType> result;
1579 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
1580 result.push_back(std::forward<Op>(op)(idx, it.get_curr()));
1601 std::vector<TupleType> result;
1603 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
1604 if (
auto t = it.get_curr(); std::forward<Pred>(
pred)(idx, t))
1605 result.push_back(t);
1633 std::vector<T> result;
1634 result.push_back(
init);
1637 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1639 acc = std::forward<Op>(op)(std::move(
acc), it.get_curr());
1640 result.push_back(
acc);
1661 using OptType = std::decay_t<decltype(std::forward<Op>(op)(
size_t{}, std::declval<TupleType>()))>;
1664 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next(), ++idx)
1665 if (
auto result = std::forward<Op>(op)(idx, it.get_curr()))
1687 while (it.has_curr())
1689 return it.completed();
1702 template <
typename Eq,
typename...
Containers>
1706 for (; it.has_curr(); it.next())
1707 if (
not std::forward<Eq>(
eq)(it.get_curr()))
1709 return it.completed();
1728 const std::tuple<const Containers1 &...> &
cs1,
1729 const std::tuple<const Containers2 &...> &
cs2)
1731 auto it1 = std::apply([](
const auto &...
cs) {
return stl_zip_it(
cs...); },
cs1);
1732 auto it2 = std::apply([](
const auto &...
cs) {
return stl_zip_it(
cs...); },
cs2);
1734 while (it1.has_curr()
and it2.has_curr())
1736 auto t1 = it1.get_curr();
1737 auto t2 = it2.get_curr();
1738 if (
t1 <
t2)
return -1;
1739 if (
t2 <
t1)
return 1;
1744 if (it1.has_curr())
return 1;
1745 if (it2.has_curr())
return -1;
1762 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1763 if (it.get_curr() ==
target)
1780 template <
typename Key,
typename...
Containers>
1785 for (
auto it =
stl_zip_it(
cs...); it.has_curr(); it.next())
1786 if (
auto t = it.get_curr(); std::get<0>(t) == key)
1787 return std::optional<TupleType>(t);
1788 return std::optional<TupleType>{};
1806 if (
not it.has_curr())
1807 return std::optional<TupleType>{};
1812 for (; it.has_curr(); it.next())
1814 auto t = it.get_curr();
1818 return std::optional<TupleType>(
min_val);
1836 if (
not it.has_curr())
1837 return std::optional<TupleType>{};
1842 for (; it.has_curr(); it.next())
1844 auto t = it.get_curr();
1848 return std::optional<TupleType>(
max_val);
1864 using ResultType = std::optional<std::pair<TupleType, TupleType>>;
1867 if (
not it.has_curr())
1874 for (; it.has_curr(); it.next())
1876 auto t = it.get_curr();
1900 if (
not it.has_curr())
1901 return std::optional<TupleType>{};
1906 for (; it.has_curr(); it.next())
1908 auto t = it.get_curr();
1915 return std::optional<TupleType>(
sum);
size_t size() const noexcept
Count the number of elements of the list.
Iterator that pairs each element with its index.
constexpr bool has_curr() const noexcept
constexpr bool operator==(const StlEnumerateIterator &other) const noexcept
constexpr auto get_curr() const
std::decay_t< Container >::const_iterator curr_
constexpr StlEnumerateIterator & operator++() noexcept
constexpr bool operator!=(const StlEnumerateIterator &other) const noexcept
std::input_iterator_tag iterator_category
constexpr auto operator*() const
std::tuple< size_t, typename std::decay_t< Container >::value_type > value_type
std::ptrdiff_t difference_type
std::decay_t< Container >::const_iterator end_
constexpr StlEnumerateIterator(const Container &c, end_tag)
constexpr StlEnumerateIterator(const Container &c)
constexpr void next() noexcept
Lazy view that pairs each element with its index.
const std::decay_t< Container > & container_
constexpr iterator begin() const
StlEnumerateIterator< std::decay_t< Container > > iterator
constexpr StlEnumerateView(const Container &c)
constexpr iterator end() const
Lazy iterator that traverses multiple STL containers in lockstep.
std::ptrdiff_t difference_type
static constexpr size_t num_containers
Number of containers being zipped.
std::input_iterator_tag iterator_category
constexpr void next() noexcept
Advance all iterators.
constexpr bool has_curr() const noexcept
Check if iterator has current element.
std::tuple< const typename std::decay_t< Containers >::value_type &... > reference
constexpr bool completed() const noexcept
Check if all iterators have completed.
std::tuple< typename std::decay_t< Containers >::value_type... > value_type
constexpr StlZipIterator(const Containers &... cs, end_tag)
constexpr StlZipIterator operator++(int) noexcept
Post-increment operator.
constexpr bool operator!=(const StlZipIterator &other) const noexcept
Inequality comparison.
constexpr StlZipIterator(const Containers &... cs)
Construct iterator from containers.
constexpr void advance_impl(std::index_sequence< Is... >) noexcept
constexpr bool completed_impl(std::index_sequence< Is... >) const noexcept
constexpr auto get_curr() const
Get current tuple of elements.
std::tuple< std::pair< typename std::decay_t< Containers >::const_iterator, typename std::decay_t< Containers >::const_iterator >... > IteratorTuple
constexpr auto operator*() const
Dereference operator for range-based for.
constexpr bool has_curr_impl(std::index_sequence< Is... >) const noexcept
constexpr auto deref_impl(std::index_sequence< Is... >) const
constexpr StlZipIterator & operator++() noexcept
Pre-increment operator.
constexpr bool operator==(const StlZipIterator &other) const noexcept
Equality comparison.
Lazy view over multiple zipped STL containers.
std::tuple< const std::decay_t< Containers > &... > containers_
StlZipIterator< std::decay_t< Containers >... > iterator
size_t size() const
Get number of tuples (minimum size of all containers).
constexpr iterator begin() const
Get iterator to beginning.
typename iterator::value_type value_type
constexpr StlZipView(const Containers &... cs)
Construct view from containers.
constexpr bool empty() const
Check if view is empty.
constexpr iterator end() const
Get iterator to end.
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Freq_Node * pred
Predecessor node in level-order traversal.
constexpr bool all_valid(const IterPairs &... its) noexcept
std::decay_t< decltype(*std::get< 0 >(std::declval< IterPair >()))> iter_value_t
constexpr void advance_all(IterPairs &... its) noexcept
bool compare_adjacent_impl(Cmp &cmp, const Tuple &t, std::index_sequence< Is... >)
constexpr auto deref_all(const IterPairs &... its)
Main namespace for Aleph-w library functions.
constexpr auto stl_zip_it(const Containers &... cs)
Get a zip iterator over STL containers.
auto stl_zip_filteri(Pred &&pred, const Containers &... cs)
Filter with index (filteri in ML).
auto stl_adjacent_map(Op &&op, const Container &c)
Apply function to adjacent pairs of elements.
bool stl_zip_exists(Pred &&pred, const Containers &... cs)
Check if predicate holds for any zipped tuple.
bool stl_zip_equal_by(Eq &&eq, const Containers &... cs)
Check equality with custom comparator.
bool stl_adjacent_exists(Pred &&pred, const Container &c)
Check if predicate holds for any adjacent pair.
auto stl_zip_find_last(Pred &&pred, const Containers &... cs)
Find last tuple satisfying predicate.
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
bool stl_zip_traverse(Pred &&pred, const Containers &... cs)
Traverse while predicate returns true.
bool stl_zip_all_eq(Pred &&pred, const Containers &... cs)
Check if predicate holds for all tuples AND containers have equal length.
auto stl_zip_min_max(const Containers &... cs)
Get both min and max in a single pass.
auto stl_zip_max(const Containers &... cs)
Get maximum tuple according to comparator.
bool stl_adjacent_all(Pred &&pred, const Container &c)
Check if predicate holds for all adjacent pairs.
auto stl_zip_take_while(Pred &&pred, const Containers &... cs)
Take tuples while predicate returns true.
size_t stl_zip_count(Pred &&pred, const Containers &... cs)
Count tuples satisfying predicate.
bool stl_zip_equal_length(const Containers &... cs)
Check if all containers have equal length.
auto stl_zip_drop_while(Pred &&pred, const Containers &... cs)
Skip tuples while predicate returns true, then return the rest.
bool stl_zip_cmp(Cmp &&cmp, const Containers &... cs)
Compare elements across containers using a comparator.
auto stl_zip_find_first(Pred &&pred, const Containers &... cs)
Find first tuple satisfying predicate.
bool stl_zip_mem(const Tuple &target, const Containers &... cs)
Check if a tuple exists in the zipped sequence (mem in ML).
auto stl_unzip_tuple(const std::vector< std::tuple< Ts... > > &tuples)
Unzip a vector of tuples into a tuple of vectors.
std::decay_t< typename HeadC::Item_Type > T
auto stl_zip_first(const Containers &... cs)
Get first tuple from zipped containers.
auto stl_zip_mapi(Op &&op, const Containers &... cs)
Map with index (mapi in ML).
int stl_zip_compare(const std::tuple< const Containers1 &... > &cs1, const std::tuple< const Containers2 &... > &cs2)
Compare two zipped sequences lexicographically.
size_t stl_zip_find_index(Pred &&pred, const Containers &... cs)
Find index of first tuple satisfying predicate.
bool stl_zip_none(Pred &&pred, const Containers &... cs)
Check if no tuple satisfies the predicate.
auto stl_zip_scan_left(T init, Op &&op, const Containers &... cs)
Scan left (scan_left in ML) - fold with intermediate results.
constexpr auto stl_enumerate(const Container &c)
Create an enumerate view over a container.
auto stl_zip_map(Op &&op, const Containers &... cs)
Map operation over zipped tuples, returning a vector.
bool stl_zip_equal(const Containers &... cs)
Check equality of zipped sequences.
auto stl_zip_sum(const Containers &... cs)
Sum all tuples element-wise (requires + operator on tuple elements).
auto stl_zip_find_mapi(Op &&op, const Containers &... cs)
Find and map with index (find_mapi in ML).
auto stl_zip_assoc(const Key &key, const Containers &... cs)
Find value associated with key in zipped pairs (assoc in ML).
auto stl_zip_filter(Pred &&pred, const Containers &... cs)
Filter zipped tuples by predicate.
auto stl_unzip(const std::vector< std::pair< T, U > > &pairs)
Unzip a vector of pairs into two vectors.
auto stl_zip_drop(const size_t n, const Containers &... cs)
Skip first n tuples, return the rest.
T stl_zip_foldl(T init, Op &&op, const Containers &... cs)
Left fold over zipped tuples.
auto stl_zip_min(const Containers &... cs)
Get minimum tuple according to comparator.
T stl_zip_reduce(T init, Op &&op, const Containers &... cs)
Alias for stl_zip_foldl (alternative name)
auto stl_zip_nth(const size_t n, const Containers &... cs)
Get n-th tuple from zipped containers.
auto stl_adjacent(const Container &c)
Zip adjacent (consecutive) elements of a container.
auto stl_zip_partition(Pred &&pred, const Containers &... cs)
Partition tuples by predicate.
constexpr auto stl_zip(const Containers &... cs)
Create a lazy zip view over STL containers.
auto stl_zip_take(const size_t n, const Containers &... cs)
Take first n tuples from zipped containers.
auto stl_zip_last(const Containers &... cs)
Get last tuple from zipped containers.
size_t stl_zip_length(const Containers &... cs)
Count total tuples (minimum length of containers).
bool stl_zip_traverse_eq(Pred &&pred, const Containers &... cs)
Traverse while predicate returns true, verify equal lengths.
void stl_zip_for_each(Op &&op, const Containers &... cs)
Apply operation to each zipped tuple (for side effects).
auto stl_zip_to_vector(const Containers &... cs)
Materialize zipped tuples into a vector.
void stl_zip_for_each_indexed(Op &&op, const Containers &... cs)
Apply operation to each tuple with its index.
bool stl_zip_all(Pred &&pred, const Containers &... cs)
Check if predicate holds for all zipped tuples.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
bool stl_zip_any(Pred &&pred, const Containers &... cs)
Alias for stl_zip_exists (Python/JS style name)
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Construct end iterator (all at end).