Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-dry-mixin.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
69#ifndef AH_DRY_MIXIN_H
70#define AH_DRY_MIXIN_H
71
72#include <cstddef>
73#include <tuple>
74#include <functional>
75#include <utility>
76#include <type_traits>
77#include <vector>
78#include <string>
79
80#include <ah-errors.H>
81
82namespace Aleph
83{
84
85// Forward declarations
86template<typename T> class DynList;
87
88// Dft_Map_Op is defined in ahFunctional.H, we just forward declare here
89// to avoid circular dependency. When ahFunctional.H is included, it provides
90// the actual definition.
91template <typename T, typename R> struct Dft_Map_Op;
92
93
94// =============================================================================
95// TraverseMixin - Basic traversal operations
96// =============================================================================
97
114template <typename Derived, typename Type>
116{
117protected:
120 {
121 return static_cast<const Derived&>(*this);
122 }
123
126 {
127 return static_cast<Derived&>(*this);
128 }
129
130public:
165 template <class Operation>
167 {
168 for (typename Derived::Iterator it(self()); it.has_curr(); it.next_ne())
169 if (not operation(it.get_curr()))
170 return false;
171 return true;
172 }
173
175 template <class Operation>
177 {
178 for (typename Derived::Iterator it(self()); it.has_curr(); it.next_ne())
179 if (not operation(it.get_curr()))
180 return false;
181 return true;
182 }
183
186 template <class Operation>
188 {
190 }
191
193 template <class Operation>
198};
199
200
201// =============================================================================
202// LocateMixin - Element location operations
203// =============================================================================
204
221template <typename Derived, typename Type>
223{
224protected:
226 {
227 return static_cast<const Derived&>(*this);
228 }
229
231 {
232 return static_cast<Derived&>(*this);
233 }
234
235public:
256 Type & nth(const size_t n) const
257 {
258 Type * ptr = nullptr;
259 size_t i = 0;
260 self().traverse([&ptr, &i, &n] (Type & item)
261 {
262 if (i++ < n)
263 return true;
264 ptr = &item;
265 return false;
266 });
267
268 ah_out_of_range_error_if(i != n + 1) << "index " << n << " out of range";
269
270 return *ptr;
271 }
272
287 Type & nth_ne(const size_t n) const noexcept
288 {
289 Type * ptr = nullptr;
290 size_t i = 0;
291 self().traverse([&ptr, &i, &n] (Type & item)
292 {
293 if (i++ < n)
294 return true;
295 ptr = &item;
296 return false;
297 });
298 return *ptr;
299 }
300
326 template <class Operation>
328 {
329 Type * ptr = nullptr;
330 self().traverse([&ptr, &operation] (Type & item)
331 {
332 if (operation(item))
333 {
334 ptr = &item;
335 return false;
336 }
337 return true;
338 });
339 return ptr;
340 }
341
344 template <class Operation>
346 {
347 Type * ptr = nullptr;
348 self().traverse([&ptr, &operation] (Type & item)
349 {
350 if (operation(item))
351 {
352 ptr = &item;
353 return false;
354 }
355 return true;
356 });
357 return ptr;
358 }
359
362 template <class Operation>
367
369 template <class Operation>
374
399 template <class Operation>
400 std::tuple<bool, Type> find_item(Operation & operation)
401 {
402 auto ptr = find_ptr(operation);
403 return ptr ? std::make_tuple(true, *ptr) : std::make_tuple(false, Type());
404 }
405
407 template <class Operation>
408 std::tuple<bool, Type> find_item(Operation & operation) const
409 {
410 auto ptr = find_ptr(operation);
411 return ptr ? std::make_tuple(true, *ptr) : std::make_tuple(false, Type());
412 }
413
415 template <class Operation>
416 std::tuple<bool, Type> find_item(Operation && operation = Operation())
417 {
418 return find_item(operation);
419 }
420
422 template <class Operation>
423 std::tuple<bool, Type> find_item(Operation && operation = Operation()) const
424 {
425 return find_item(operation);
426 }
427};
428
429
430// =============================================================================
431// FunctionalMixin - Functional programming operations
432// =============================================================================
433
456template <typename Derived, typename Type>
458{
459protected:
461 {
462 return static_cast<const Derived&>(*this);
463 }
464
466 {
467 return static_cast<Derived&>(*this);
468 }
469
470public:
471
472 // ---------------------------------------------------------------------------
473 // Iteration
474 // ---------------------------------------------------------------------------
475
492 template <class Operation>
493 auto for_each(Operation & operation) const -> decltype(self())
494 {
495 self().traverse([&operation] (const Type & item)
496 {
497 operation(item);
498 return true;
499 });
500 return self();
501 }
502
504 template <class Operation>
505 auto for_each(Operation & operation) -> decltype(self())
506 {
507 self().traverse([&operation] (const Type & item)
508 {
509 operation(item);
510 return true;
511 });
512 return self();
513 }
514
516 template <class Operation>
521
523 template <class Operation>
524 auto for_each(Operation && operation = Operation()) -> decltype(self())
525 {
527 }
528
544 template <class Operation>
546 {
547 self().traverse([&operation] (Type & item)
548 {
549 operation(item);
550 return true;
551 });
552 return self();
553 }
554
556 template <class Operation>
558 {
560 }
561
562 // ---------------------------------------------------------------------------
563 // Predicates
564 // ---------------------------------------------------------------------------
565
584 template <class Operation>
586 {
587 return self().template traverse<Operation>(operation);
588 }
589
591 template <class Operation>
593 {
595 }
596
600 template <class Operation>
602 {
604 }
605
607 template <class Operation>
609 {
611 }
612
631 template <class Operation>
633 {
634 return not self().traverse([&operation] (const Type & item)
635 {
636 return not operation(item);
637 });
638 }
639
641 template <class Operation>
643 {
645 }
646
647 // ---------------------------------------------------------------------------
648 // Transformation
649 // ---------------------------------------------------------------------------
650
678 template <typename __Type = Type,
679 template <typename> class Container = Aleph::DynList,
682 {
684 for_each([&ret_val, &operation] (const Type & item)
685 {
686 ret_val.append(operation(item));
687 });
688 return ret_val;
689 }
690
692 template <typename __Type = Type,
693 template <typename> class Container = Aleph::DynList,
699
729 template <typename __Type = Type>
731 std::function<__Type(const __Type&, const Type&)> operation) const
732 {
733 auto ret_val = init;
734 for_each([&ret_val, &operation] (const Type & item)
735 {
736 ret_val = operation(ret_val, item);
737 });
738 return ret_val;
739 }
740
744 template <typename __Type = Type>
745 [[nodiscard]] __Type fold_left(std::function<__Type(const __Type&, const Type&)> operation,
746 const __Type & init) const
747 {
749 }
750
760 template <class Operation>
762 {
763 auto ret_val = init;
764 for_each([&ret_val, &operation] (const Type & item)
765 {
766 ret_val = operation(ret_val, item);
767 });
768 return ret_val;
769 }
770
772 template <class Operation>
774 {
776 }
777
797 template <class Operation>
799 {
801 for_each([&ret_val, &operation] (const Type & item)
802 {
803 if (operation(item))
804 ret_val.append(item);
805 });
806 return ret_val;
807 }
808
810 template <class Operation>
815
831 template <class Operation>
833 {
835 size_t i = 0;
836 for_each([&ret_val, &operation, &i] (const Type & item)
837 {
838 if (operation(item))
839 ret_val.append(std::make_tuple(item, i));
840 ++i;
841 });
842 return ret_val;
843 }
844
846 template <class Operation>
851
868 template <class Operation>
869 [[nodiscard]] std::pair<DynList<Type>, DynList<Type>> partition(Operation & op) const
870 {
871 std::pair<DynList<Type>, DynList<Type>> ret_val;
872 for_each([&ret_val, &op] (const Type & item)
873 {
874 if (op(item))
875 ret_val.first.append(item);
876 else
877 ret_val.second.append(item);
878 });
879 return ret_val;
880 }
881
883 template <class Operation>
884 [[nodiscard]] std::pair<DynList<Type>, DynList<Type>> partition(Operation && op = Operation()) const
885 {
886 return partition<Operation>(op);
887 }
888
892 template <class Operation>
893 [[nodiscard]] std::tuple<DynList<Type>, DynList<Type>> tpartition(Operation & op) const
894 {
895 DynList<Type> r1, r2;
896 for_each([&r1, &r2, &op] (const Type & item)
897 {
898 if (op(item))
899 r1.append(item);
900 else
901 r2.append(item);
902 });
903 return std::make_tuple(r1, r2);
904 }
905
907 template <class Operation>
908 [[nodiscard]] std::tuple<DynList<Type>, DynList<Type>> tpartition(Operation && op = Operation()) const
909 {
910 return tpartition<Operation>(op);
911 }
912
913 // ---------------------------------------------------------------------------
914 // Utility
915 // ---------------------------------------------------------------------------
916
927 {
928 size_t count = 0;
929 for_each([&count] (const Type &) { ++count; });
930 return count;
931 }
932
948 template <template <typename> class Container = Aleph::DynList>
950 {
952 for_each([&ret_val] (const Type & item)
953 {
954 ret_val.insert(item);
955 });
956 return ret_val;
957 }
958
959 // ---------------------------------------------------------------------------
960 // Slicing
961 // ---------------------------------------------------------------------------
962
979 template <template <typename> class Container = Aleph::DynList>
980 [[nodiscard]] Container<Type> take(const size_t n) const
981 {
982 size_t i = 0;
984 self().traverse([&i, &ret, n] (const Type & item)
985 {
986 if (i++ >= n)
987 return false;
988 ret.append(item);
989 return true;
990 });
991 return ret;
992 }
993
1010 template <template <typename> class Container = Aleph::DynList>
1011 [[nodiscard]] Container<Type> drop(const size_t n) const
1012 {
1013 size_t i = 0;
1015 self().traverse([&i, &ret, n] (const Type & item)
1016 {
1017 if (i++ >= n)
1018 ret.append(item);
1019 return true;
1020 });
1021 return ret;
1022 }
1023
1024 // ---------------------------------------------------------------------------
1025 // Aggregation (Numeric)
1026 // ---------------------------------------------------------------------------
1027
1046 [[nodiscard]] Type sum(const Type & init = Type{}) const
1047 requires requires(Type a, Type b) { { a + b } -> std::convertible_to<Type>; }
1048 {
1049 Type result = init;
1050 for_each([&result] (const Type & item)
1051 {
1052 result = result + item;
1053 });
1054 return result;
1055 }
1056
1074 [[nodiscard]] Type product(const Type & init) const
1075 requires requires(Type a, Type b) { { a * b } -> std::convertible_to<Type>; }
1076 {
1077 Type result = init;
1078 for_each([&result] (const Type & item)
1079 {
1080 result = result * item;
1081 });
1082 return result;
1083 }
1084
1101 [[nodiscard]] const Type * min() const
1102 requires requires(Type a, Type b) { { a < b } -> std::convertible_to<bool>; }
1103 {
1104 const Type * result = nullptr;
1105 for_each([&result] (const Type & item)
1106 {
1107 if (result == nullptr or item < *result)
1108 result = &item;
1109 });
1110 return result;
1111 }
1112
1129 [[nodiscard]] const Type * max() const
1130 requires requires(Type a, Type b) { { a < b } -> std::convertible_to<bool>; }
1131 {
1132 const Type * result = nullptr;
1133 for_each([&result] (const Type & item)
1134 {
1135 if (result == nullptr or *result < item)
1136 result = &item;
1137 });
1138 return result;
1139 }
1140
1158 template <class Compare>
1159 [[nodiscard]] const Type * min_by(Compare cmp) const
1160 {
1161 const Type * result = nullptr;
1162 for_each([&result, &cmp] (const Type & item)
1163 {
1164 if (result == nullptr or cmp(item, *result))
1165 result = &item;
1166 });
1167 return result;
1168 }
1169
1187 template <class Compare>
1188 [[nodiscard]] const Type * max_by(Compare cmp) const
1189 {
1190 const Type * result = nullptr;
1191 for_each([&result, &cmp] (const Type & item)
1192 {
1193 if (result == nullptr or cmp(*result, item))
1194 result = &item;
1195 });
1196 return result;
1197 }
1198
1199 // ---------------------------------------------------------------------------
1200 // Search and Counting
1201 // ---------------------------------------------------------------------------
1202
1224 [[nodiscard]] bool has_value(const Type & val) const
1225 requires requires(Type a, Type b) { { a == b } -> std::convertible_to<bool>; }
1226 {
1227 return exists([&val] (const Type & item) { return item == val; });
1228 }
1229
1247 template <class Predicate>
1248 [[nodiscard]] bool none(Predicate & pred) const
1249 {
1250 return not exists(pred);
1251 }
1252
1254 template <class Predicate>
1255 [[nodiscard]] bool none(Predicate && pred) const
1256 {
1257 return not exists(std::forward<Predicate>(pred));
1258 }
1259
1275 template <class Predicate>
1277 {
1278 size_t count = 0;
1279 for_each([&count, &pred] (const Type & item)
1280 {
1281 if (pred(item))
1282 ++count;
1283 });
1284 return count;
1285 }
1286
1287 // ---------------------------------------------------------------------------
1288 // First/Last Element Access
1289 // ---------------------------------------------------------------------------
1290
1304 [[nodiscard]] const Type * first() const
1305 {
1306 const Type * result = nullptr;
1307 self().traverse([&result] (const Type & item)
1308 {
1309 result = &item;
1310 return false; // stop after first
1311 });
1312 return result;
1313 }
1314
1330 {
1331 auto ptr = first();
1332 return ptr ? *ptr : default_val;
1333 }
1334
1348 [[nodiscard]] const Type * last() const
1349 {
1350 const Type * result = nullptr;
1351 for_each([&result] (const Type & item)
1352 {
1353 result = &item;
1354 });
1355 return result;
1356 }
1357
1373 {
1374 auto ptr = last();
1375 return ptr ? *ptr : default_val;
1376 }
1377
1378 // ---------------------------------------------------------------------------
1379 // Enumeration and Indexing
1380 // ---------------------------------------------------------------------------
1381
1398 template <template <typename> class Container = Aleph::DynList>
1400 {
1402 size_t idx = 0;
1403 for_each([&ret, &idx] (const Type & item)
1404 {
1405 ret.append(std::make_pair(idx++, item));
1406 });
1407 return ret;
1408 }
1409
1425 template <class Predicate>
1427 {
1428 size_t idx = 0;
1429 size_t result = static_cast<size_t>(-1);
1430 self().traverse([&idx, &result, &pred] (const Type & item)
1431 {
1432 if (pred(item))
1433 {
1434 result = idx;
1435 return false;
1436 }
1437 ++idx;
1438 return true;
1439 });
1440 return result;
1441 }
1442
1461 [[nodiscard]] size_t index_of(const Type & val) const
1462 requires requires(Type a, Type b) { { a == b } -> std::convertible_to<bool>; }
1463 {
1464 return find_index([&val] (const Type & item) { return item == val; });
1465 }
1466
1467 // ---------------------------------------------------------------------------
1468 // Transformation (Advanced)
1469 // ---------------------------------------------------------------------------
1470
1488 template <template <typename> class Container = Aleph::DynList>
1490 requires requires(Type a, Type b) { { a == b } -> std::convertible_to<bool>; }
1491 {
1493 const Type * prev = nullptr;
1494 for_each([&ret, &prev] (const Type & item)
1495 {
1496 if (prev == nullptr or not (*prev == item))
1497 {
1498 ret.append(item);
1499 prev = &item;
1500 }
1501 });
1502 return ret;
1503 }
1504
1523 template <template <typename> class Container = Aleph::DynList, class EqPred>
1525 {
1527 const Type * prev = nullptr;
1528 for_each([&ret, &prev, &eq] (const Type & item)
1529 {
1530 if (prev == nullptr or not eq(*prev, item))
1531 {
1532 ret.append(item);
1533 prev = &item;
1534 }
1535 });
1536 return ret;
1537 }
1538
1554 template <template <typename> class Container = Aleph::DynList>
1556 {
1558 bool first = true;
1559 for_each([&ret, &sep, &first] (const Type & item)
1560 {
1561 if (not first)
1562 ret.append(sep);
1563 ret.append(item);
1564 first = false;
1565 });
1566 return ret;
1567 }
1568
1569 // ---------------------------------------------------------------------------
1570 // Chunking and Windowing
1571 // ---------------------------------------------------------------------------
1572
1588 template <template <typename> class Container = Aleph::DynList>
1590 {
1592 if (n == 0) return ret;
1593
1594 Container<Type> current;
1595 size_t count = 0;
1596
1597 for_each([&ret, &current, &count, n] (const Type & item)
1598 {
1599 current.append(item);
1600 if (++count >= n)
1601 {
1602 ret.append(std::move(current));
1603 current = Container<Type>{};
1604 count = 0;
1605 }
1606 });
1607
1608 if (count > 0)
1609 ret.append(std::move(current));
1610
1611 return ret;
1612 }
1613
1631 template <template <typename> class Container = Aleph::DynList>
1632 [[nodiscard]] Container<Container<Type>> sliding(size_t size, size_t step = 1) const
1633 {
1635 if (size == 0 or step == 0) return ret;
1636
1637 // Collect all elements first
1639 for_each([&all] (const Type & item) { all.append(item); });
1640
1641 size_t total = all.size();
1642 if (total < size) return ret;
1643
1644 for (size_t start = 0; start + size <= total; start += step)
1645 {
1647 size_t idx = 0;
1648 all.traverse([&window, &idx, start, size] (const Type & item)
1649 {
1650 if (idx >= start and idx < start + size)
1651 window.append(item);
1652 ++idx;
1653 return idx < start + size;
1654 });
1655 ret.append(std::move(window));
1656 }
1657
1658 return ret;
1659 }
1660
1661 // ---------------------------------------------------------------------------
1662 // Conversion
1663 // ---------------------------------------------------------------------------
1664
1678 [[nodiscard]] std::vector<Type> to_vector() const
1679 {
1680 std::vector<Type> ret;
1681 if constexpr (requires { self().size(); })
1682 ret.reserve(self().size());
1683 for_each([&ret] (const Type & item) { ret.push_back(item); });
1684 return ret;
1685 }
1686
1705 template <typename DynListType = DynList<Type>>
1707 {
1709 for_each([&ret] (const Type & item) { ret.append(item); });
1710 return ret;
1711 }
1712
1730 template <typename StringType = std::string>
1732 requires requires(Type a) { std::to_string(a); }
1733 {
1735 bool first = true;
1736 for_each([&ret, &sep, &first] (const Type & item)
1737 {
1738 if (not first)
1739 ret += sep;
1740 ret += std::to_string(item);
1741 first = false;
1742 });
1743 return ret;
1744 }
1745
1760 [[nodiscard]] std::string join_str(const std::string & sep = ", ") const
1762 {
1763 std::string ret;
1764 bool first = true;
1765 for_each([&ret, &sep, &first] (const Type & item)
1766 {
1767 if (not first)
1768 ret += sep;
1769 ret += static_cast<std::string>(item);
1770 first = false;
1771 });
1772 return ret;
1773 }
1774
1775 // ---------------------------------------------------------------------------
1776 // Zip Operations
1777 // ---------------------------------------------------------------------------
1778
1798 template <class Other, template <typename> class Container = Aleph::DynList>
1800 zip_with(const Other & other) const
1801 {
1802 using OtherType = typename Other::Item_Type;
1804
1805 auto it1 = self().get_it();
1806 auto it2 = other.get_it();
1807
1808 while (it1.has_curr() and it2.has_curr())
1809 {
1810 ret.append(std::make_pair(it1.get_curr(), it2.get_curr()));
1811 it1.next();
1812 it2.next();
1813 }
1814
1815 return ret;
1816 }
1817};
1818
1819
1820// =============================================================================
1821// KeysMixin - Keys/Items extraction
1822// =============================================================================
1823
1829template <typename Derived, typename Type>
1831{
1832protected:
1834 {
1835 return static_cast<const Derived&>(*this);
1836 }
1837
1838public:
1844 template <template <typename> class Container = DynList>
1846 {
1847 return self().template maps<Type, Container>([] (const Type & key)
1848 {
1849 return key;
1850 });
1851 }
1852
1856 template <template <typename> class Container = DynList>
1858 {
1859 return keys<Container>();
1860 }
1861};
1862
1863
1864} // end namespace Aleph
1865
1866#endif // AH_DRY_MIXIN_H
1867
Exception handling system with formatted messages for Aleph-w.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
CRTP Mixin providing functional programming operations.
Derived & self() noexcept
size_t find_index(Predicate pred) const
Find the index of the first element satisfying a predicate.
bool all(Operation &&operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool all(Operation &operation) const
Test if all elements satisfy a predicate.
const Type * min_by(Compare cmp) const
Find the minimum element using a custom comparator.
Type fold(const Type &init, Operation &&operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
DynList< Type > filter(Operation &&operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
auto mutable_for_each(Operation &operation) -> decltype(self())
Apply an operation to each element (mutable).
__Type fold_left(std::function< __Type(const __Type &, const Type &)> operation, const __Type &init) const
Left fold with operation first (alternative signature).
Container< Type > drop(const size_t n) const
Skip the first n elements.
Container< std::pair< size_t, Type > > enumerate() const
Enumerate elements with their indices.
Container< Container< Type > > chunk(size_t n) const
Split into chunks of fixed size.
auto mutable_for_each(Operation &&operation=Operation()) -> decltype(self())
This is an overloaded member function, provided for convenience. It differs from the above function o...
size_t count_if(Predicate pred) const
Count elements satisfying a predicate.
DynListType to_dynlist() const
Convert container to DynList.
DynList< Type > filter(Operation &operation) const
Filter elements by a predicate.
std::pair< DynList< Type >, DynList< Type > > partition(Operation &&op=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
DynList< std::tuple< Type, size_t > > pfilter(Operation &&operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
const Type * max() const
Find the maximum element.
bool forall(Operation &&operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
DynList< std::tuple< Type, size_t > > pfilter(Operation &operation) const
Filter with position information.
bool exists(Operation &&operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
auto for_each(Operation &&operation=Operation()) const -> decltype(self())
This is an overloaded member function, provided for convenience. It differs from the above function o...
Container< Type > rev() const
Create a reversed copy.
Container< __Type > maps(Operation &operation) const
Transform elements using a mapping function.
Container< Container< Type > > sliding(size_t size, size_t step=1) const
Create sliding windows of fixed size.
Type fold(const Type &init, Operation &operation) const
Simple fold with same type for accumulator and elements.
Container< Type > take(const size_t n) const
Take the first n elements.
std::string join_str(const std::string &sep=", ") const
Join string elements with separator.
Container< Type > unique() const
Remove consecutive duplicate elements.
const Type * first() const
Get the first element.
Container< std::pair< Type, typename Other::Item_Type > > zip_with(const Other &other) const
Zip with another container.
bool none(Predicate &pred) const
Check if no element satisfies a predicate.
Type last_or(const Type &default_val) const
Get the last element or a default value.
bool has_value(const Type &val) const
Check if container has a value.
StringType join(const StringType &sep=StringType{", "}) const
Join elements into a string with separator.
bool exists(Operation &operation) const
Test if any element satisfies a predicate.
size_t index_of(const Type &val) const
Find the index of a specific value.
__Type foldl(const __Type &init, std::function< __Type(const __Type &, const Type &)> operation) const
Left fold (reduce) with initial value.
auto for_each(Operation &operation) -> decltype(self())
This is an overloaded member function, provided for convenience. It differs from the above function o...
auto for_each(Operation &operation) const -> decltype(self())
Apply an operation to each element (read-only).
Type product(const Type &init) const
Compute the product of all elements.
std::tuple< DynList< Type >, DynList< Type > > tpartition(Operation &&op=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
size_t length() const noexcept
Count the number of elements.
Container< Type > unique_by(EqPred eq) const
Remove consecutive duplicates using a custom equality predicate.
Type sum(const Type &init=Type{}) const
Compute the sum of all elements.
const Type * max_by(Compare cmp) const
Find the maximum element using a custom comparator.
std::pair< DynList< Type >, DynList< Type > > partition(Operation &op) const
Partition elements by a predicate.
std::vector< Type > to_vector() const
Convert to std::vector.
bool none(Predicate &&pred) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
const Derived & self() const noexcept
Container< Type > intersperse(const Type &sep) const
Intersperse a separator between elements.
auto for_each(Operation &&operation=Operation()) -> decltype(self())
This is an overloaded member function, provided for convenience. It differs from the above function o...
std::tuple< DynList< Type >, DynList< Type > > tpartition(Operation &op) const
Partition returning tuple instead of pair.
Container< __Type > maps(Operation &&operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Type first_or(const Type &default_val) const
Get the first element or a default value.
bool forall(Operation &operation) const
Alias for all().
const Type * last() const
Get the last element.
const Type * min() const
Find the minimum element.
CRTP Mixin for extracting keys from set-like containers.
Container< Type > items() const
Alias for keys().
const Derived & self() const noexcept
Container< Type > keys() const
Extract all keys as a list.
CRTP Mixin providing element location operations.
std::tuple< bool, Type > find_item(Operation &operation)
Find element with success flag.
Type * find_ptr(Operation &operation) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
std::tuple< bool, Type > find_item(Operation &&operation=Operation())
This is an overloaded member function, provided for convenience. It differs from the above function o...
Type * find_ptr(Operation &operation)
Find the first element satisfying a predicate.
std::tuple< bool, Type > find_item(Operation &&operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
std::tuple< bool, Type > find_item(Operation &operation) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Type & nth_ne(const size_t n) const noexcept
Access the n-th element (unchecked).
const Derived & self() const noexcept
Type * find_ptr(Operation and operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Type * find_ptr(Operation and operation=Operation())
This is an overloaded member function, provided for convenience. It differs from the above function o...
Type & nth(const size_t n) const
Access the n-th element (bounds-checked).
Derived & self() noexcept
CRTP Mixin providing traversal operations.
bool traverse(Operation &operation)
This is an overloaded member function, provided for convenience. It differs from the above function o...
const Derived & self() const noexcept
Access the derived class (const version).
bool traverse(Operation and operation=Operation())
This is an overloaded member function, provided for convenience. It differs from the above function o...
Derived & self() noexcept
Access the derived class (mutable version).
bool traverse(Operation and operation=Operation()) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool traverse(Operation &operation) const
Traverse all elements, applying an operation to each.
int cmp(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4118
Freq_Node * pred
Predecessor node in level-order traversal.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
bool eq(const C1 &c1, const C2 &c2, Eq e=Eq())
Check equality of two containers using a predicate.
size_t size(Node *root) noexcept
static bool init
Definition hash-fct.C:47
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.
Definition ahAlgo.H:127
STL namespace.
Default mapping operation (identity).
bool traverse(Operation &operation) noexcept(traverse_is_noexcept< Operation >())
Traverse the container via its iterator and performs a conditioned operation on each item.
Definition ah-dry.H:95