Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
ah-ranges.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
111#ifndef AH_RANGES_H
112#define AH_RANGES_H
113
114// Check for C++20 ranges support
115// We need both the header AND the actual implementation.
116// libc++ in Clang 14 has <ranges> header but incomplete implementation.
117//
118// Detection strategy:
119// - GCC 11+: __cpp_lib_ranges >= 202106L (basic ranges support)
120// - GCC 12+: __cpp_lib_ranges >= 202110L (complete ranges support)
121// - Clang with libc++: Often has <ranges> but incomplete std::views
122//
123// We accept __cpp_lib_ranges >= 202106L for GCC, but exclude Clang + libc++
124// which has the header but incomplete views implementation.
125#if __cplusplus >= 202002L && __has_include(<ranges>)
126# include <ranges>
127# include <algorithm>
128# include <iterator>
129# include <concepts>
130# if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 202106L
131 // Exclude Clang with libc++ (incomplete std::views implementation)
132# if defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 160000
133# define ALEPH_HAS_RANGES 0
134# else
135# define ALEPH_HAS_RANGES 1
136# endif
137# else
138# define ALEPH_HAS_RANGES 0
139# endif
140#else
141# define ALEPH_HAS_RANGES 0
142#endif
143
144// Feature detection for C++23 views
145#ifdef __cpp_lib_ranges_stride
146# define ALEPH_HAS_STRIDE 1
147#else
148# define ALEPH_HAS_STRIDE 0
149#endif
150
151#ifdef __cpp_lib_ranges_repeat
152# define ALEPH_HAS_REPEAT 1
153#else
154# define ALEPH_HAS_REPEAT 0
155#endif
156
157#ifdef __cpp_lib_ranges_zip
158# define ALEPH_HAS_ZIP 1
159#else
160# define ALEPH_HAS_ZIP 0
161#endif
162
163#ifdef __cpp_lib_ranges_enumerate
164# define ALEPH_HAS_ENUMERATE 1
165#else
166# define ALEPH_HAS_ENUMERATE 0
167#endif
168
169#include <type_traits>
170#include <utility>
171#include <tuple>
172#include <functional>
173
174namespace Aleph
175{
176
177// Forward declarations for major Aleph containers with simple template signatures.
178// Containers with complex template signatures (like DynSetTree, DynBinHeap)
179// should use the generic to<Container>() adaptor instead.
180template <typename T> class DynList;
181template <typename T> class DynArray;
182template <typename T> class DynDlist;
183template <typename T> class DynListStack;
184template <typename T> class DynListQueue;
185template <typename T> class ArrayStack;
186template <typename T> class ArrayQueue;
187template <typename T> class Random_Set;
188
189#if ALEPH_HAS_RANGES
190
191// ============================================================================
192// Concepts for Aleph containers
193// ============================================================================
194
203template <typename C>
204concept AlephContainer = requires(C c) {
205 typename C::Iterator;
206 typename C::Item_Type;
207 { c.begin() } -> std::input_or_output_iterator;
208 { c.end() } -> std::sentinel_for<decltype(c.begin())>;
209};
210
214template <typename C>
215concept AlephAppendable = AlephContainer<C> && requires(C c, typename C::Item_Type v) {
216 c.append(v);
217};
218
222template <typename R>
223concept RangeLike = std::ranges::range<R>;
224
225// ============================================================================
226// Range Adaptors - Convert ranges to Aleph containers
227// ============================================================================
228
246template <AlephAppendable Container, RangeLike R>
248{
249 Container result;
250 for (auto&& elem : r)
251 result.append(std::forward<decltype(elem)>(elem));
252 return result;
253}
254
255// ============================================================================
256// Lazy Range Generation (zero-allocation until materialized)
257// ============================================================================
258
283template <typename T = int>
284[[nodiscard]] constexpr auto lazy_range(T start, T end)
285{
286 return std::views::iota(start, end);
287}
288
295template <typename T = int>
296[[nodiscard]] constexpr auto lazy_range(T n)
297{
298 return std::views::iota(T{0}, n);
299}
300
316template <typename T = int>
317[[nodiscard]] constexpr auto lazy_iota(T start = T{0})
318{
319 return std::views::iota(start);
320}
321
322#if ALEPH_HAS_REPEAT
330template <typename T>
331[[nodiscard]] constexpr auto lazy_repeat(const T& value, size_t n)
332{
333 return std::views::repeat(value) | std::views::take(n);
334}
335#endif
336
337// ============================================================================
338// Internal Utilities using Ranges (for performance optimization)
339// ============================================================================
340
341namespace detail
342{
343
349template <RangeLike R, typename Pred>
350[[nodiscard]] constexpr bool ranges_all_of(R&& r, Pred&& pred)
351{
352 return std::ranges::all_of(std::forward<R>(r), std::forward<Pred>(pred));
353}
354
360template <RangeLike R, typename Pred>
361[[nodiscard]] constexpr bool ranges_any_of(R&& r, Pred&& pred)
362{
363 return std::ranges::any_of(std::forward<R>(r), std::forward<Pred>(pred));
364}
365
371template <RangeLike R, typename Pred>
372[[nodiscard]] constexpr bool ranges_none_of(R&& r, Pred&& pred)
373{
374 return std::ranges::none_of(std::forward<R>(r), std::forward<Pred>(pred));
375}
376
382template <RangeLike R, typename Pred>
383[[nodiscard]] constexpr auto ranges_find_if(R&& r, Pred&& pred)
384{
385 return std::ranges::find_if(std::forward<R>(r), std::forward<Pred>(pred));
386}
387
391template <RangeLike R, typename Pred>
392[[nodiscard]] constexpr auto ranges_count_if(R&& r, Pred&& pred)
393{
394 return std::ranges::count_if(std::forward<R>(r), std::forward<Pred>(pred));
395}
396
402template <RangeLike R, typename Func>
403[[nodiscard]] constexpr auto ranges_transform(R&& r, Func&& func)
404{
405 return std::forward<R>(r) | std::views::transform(std::forward<Func>(func));
406}
407
413template <RangeLike R, typename Pred>
414[[nodiscard]] constexpr auto ranges_filter(R&& r, Pred&& pred)
415{
416 return std::forward<R>(r) | std::views::filter(std::forward<Pred>(pred));
417}
418
422template <RangeLike R>
423[[nodiscard]] constexpr auto ranges_take(R&& r, size_t n)
424{
425 return std::forward<R>(r) | std::views::take(n);
426}
427
431template <RangeLike R>
432[[nodiscard]] constexpr auto ranges_drop(R&& r, size_t n)
433{
434 return std::forward<R>(r) | std::views::drop(n);
435}
436
442template <RangeLike R>
443 requires std::ranges::bidirectional_range<R>
444[[nodiscard]] constexpr auto ranges_reverse(R&& r)
445{
446 return std::forward<R>(r) | std::views::reverse;
447}
448
452template <RangeLike R>
453[[nodiscard]] constexpr auto ranges_flatten(R&& r)
454{
455 return std::forward<R>(r) | std::views::join;
456}
457
458#if ALEPH_HAS_ZIP
462template <RangeLike... Rs>
463[[nodiscard]] constexpr auto ranges_zip(Rs&&... rs)
464{
465 return std::views::zip(std::forward<Rs>(rs)...);
466}
467#endif
468
469#if ALEPH_HAS_ENUMERATE
473template <RangeLike R>
474[[nodiscard]] constexpr auto ranges_enumerate(R&& r)
475{
476 return std::forward<R>(r) | std::views::enumerate;
477}
478#endif
479
485template <RangeLike R, typename T, typename BinaryOp>
486[[nodiscard]] constexpr T ranges_fold_left(R&& r, T init, BinaryOp&& op)
487{
488#ifdef __cpp_lib_ranges_fold
489 return std::ranges::fold_left(std::forward<R>(r), init, std::forward<BinaryOp>(op));
490#else
491 // Fallback for C++20 - use explicit variable to avoid rvalue issues
492 for (auto&& elem : r)
493 init = op(init, elem);
494 return init;
495#endif
496}
497
501template <RangeLike R>
502[[nodiscard]] constexpr auto ranges_sum(R&& r)
503{
504 using T = std::ranges::range_value_t<R>;
505 return ranges_fold_left(std::forward<R>(r), T{0}, std::plus<>{});
506}
507
511template <RangeLike R>
512[[nodiscard]] constexpr auto ranges_product(R&& r)
513{
514 using T = std::ranges::range_value_t<R>;
515 return ranges_fold_left(std::forward<R>(r), T{1}, std::multiplies<>{});
516}
517
521template <RangeLike R>
522[[nodiscard]] constexpr auto ranges_min(R&& r)
523{
524 return std::ranges::min_element(std::forward<R>(r));
525}
526
530template <RangeLike R>
531[[nodiscard]] constexpr auto ranges_max(R&& r)
532{
533 return std::ranges::max_element(std::forward<R>(r));
534}
535
539template <RangeLike R, typename Comp = std::less<>>
540constexpr void ranges_sort(R&& r, Comp&& comp = Comp{})
541{
542 std::ranges::sort(std::forward<R>(r), std::forward<Comp>(comp));
543}
544
545} // namespace detail
546
547// ============================================================================
548// Pipe Operator Support for Aleph Containers
549// ============================================================================
550
558struct aleph_adaptor_tag {};
559
563template <typename T>
564concept AlephAdaptor = std::derived_from<std::remove_cvref_t<T>, aleph_adaptor_tag>;
565
575template <typename R, AlephAdaptor Adaptor>
576 requires std::ranges::range<std::remove_cvref_t<R>>
577[[nodiscard]] auto operator|(R&& r, const Adaptor& adaptor)
578{
579 return adaptor(std::forward<R>(r));
580}
581
587template <template <typename> class Container>
589{
590 template <typename R>
591 requires std::ranges::range<std::remove_cvref_t<R>>
592 [[nodiscard]] auto operator()(R&& r) const
593 {
594 using T = std::ranges::range_value_t<std::remove_cvref_t<R>>;
595 Container<T> result;
596 for (auto&& elem : r)
597 result.append(std::forward<decltype(elem)>(elem));
598 return result;
599 }
600};
601
612inline constexpr to_aleph_adaptor<DynList> to_dynlist_v{};
613
618
623
627template <template <typename> class Container>
629{
630 template <typename R>
631 requires std::ranges::range<std::remove_cvref_t<R>>
632 [[nodiscard]] auto operator()(R&& r) const
633 {
634 using T = std::ranges::range_value_t<std::remove_cvref_t<R>>;
635 Container<T> result;
636 for (auto&& elem : r)
637 result.push(std::forward<decltype(elem)>(elem));
638 return result;
639 }
640};
641
647
652
656template <template <typename> class Container>
658{
659 template <typename R>
660 requires std::ranges::range<std::remove_cvref_t<R>>
661 [[nodiscard]] auto operator()(R&& r) const
662 {
663 using T = std::ranges::range_value_t<std::remove_cvref_t<R>>;
664 Container<T> result;
665 for (auto&& elem : r)
666 result.put(std::forward<decltype(elem)>(elem));
667 return result;
668 }
669};
670
675
680
685
689template <template <typename, typename...> class Container, typename... ExtraArgs>
691{
692 template <typename R>
693 requires std::ranges::range<std::remove_cvref_t<R>>
694 [[nodiscard]] auto operator()(R&& r) const
695 {
696 using T = std::ranges::range_value_t<std::remove_cvref_t<R>>;
697 Container<T, ExtraArgs...> result;
698 for (auto&& elem : r)
699 result.insert(std::forward<decltype(elem)>(elem));
700 return result;
701 }
702};
703
723template <typename Container, RangeLike R>
725{
726 Container result;
727 for (auto&& elem : r)
728 {
729 if constexpr (requires { result.append(elem); })
730 result.append(std::forward<decltype(elem)>(elem));
731 else if constexpr (requires { result.insert(elem); })
732 result.insert(std::forward<decltype(elem)>(elem));
733 else if constexpr (requires { result.push(elem); })
734 result.push(std::forward<decltype(elem)>(elem));
735 else
736 static_assert(sizeof(Container) == 0,
737 "Container must have append(), insert(), or push() method");
738 }
739 return result;
740}
741
753template <typename Container>
755{
756 template <typename R>
757 requires std::ranges::range<std::remove_cvref_t<R>>
758 [[nodiscard]] Container operator()(R&& r) const
759 {
760 return collect<Container>(std::forward<R>(r));
761 }
762};
763
777template <typename Container>
778[[nodiscard]] constexpr to_adaptor<Container> to() { return {}; }
779
780#else // !ALEPH_HAS_RANGES
781
782// ============================================================================
783// Fallback for C++17 and earlier
784// ============================================================================
785
786// Define ALEPH_HAS_RANGES as 0 for feature detection
787// The public API in ahFunctional.H will be used instead
788
789namespace detail
790{
791
792// Fallback implementations that work without ranges
793template <typename Container, typename Pred>
795{
796 for (auto it = c.get_it(); it.has_curr(); it.next_ne())
797 if (!pred(it.get_curr()))
798 return false;
799 return true;
800}
801
802template <typename Container, typename Pred>
804{
805 for (auto it = c.get_it(); it.has_curr(); it.next_ne())
806 if (pred(it.get_curr()))
807 return true;
808 return false;
809}
810
811template <typename Container, typename Pred>
813{
814 return !fallback_any_of(c, std::forward<Pred>(pred));
815}
816
823template <typename Container, typename T, typename BinaryOp>
825{
826 for (auto&& elem : c)
827 init = op(std::move(init), elem);
828 return init;
829}
830
834template <typename Container, typename Pred>
836{
837 for (const auto& elem : c)
838 if (!pred(elem))
839 return false;
840 return true;
841}
842
846template <typename Container, typename Pred>
848{
849 for (const auto& elem : c)
850 if (pred(elem))
851 return true;
852 return false;
853}
854
858template <typename Container, typename Pred>
860{
861 return !ranges_any_of(c, std::forward<Pred>(pred));
862}
863
867template <typename Container, typename Pred>
869{
870 size_t count = 0;
871 for (const auto& elem : c)
872 if (pred(elem))
873 ++count;
874 return count;
875}
876
877} // namespace detail
878
879#endif // ALEPH_HAS_RANGES
880
881} // namespace Aleph
882
883#endif // AH_RANGES_H
T & insert(const T &item)
Insert a new item by copy.
Definition htlist.H:1502
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
iterator begin() noexcept
Return an STL-compatible iterator to the first element.
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_binary_ior > > operator|(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4035
Freq_Node * pred
Predecessor node in level-order traversal.
bool fallback_all_of(const Container &c, Pred &&pred)
Definition ah-ranges.H:794
auto ranges_count_if(const Container &c, Pred &&pred)
Fallback count_if using range-based for loop.
Definition ah-ranges.H:868
bool fallback_any_of(const Container &c, Pred &&pred)
Definition ah-ranges.H:803
constexpr T ranges_fold_left(Container &&c, T init, BinaryOp &&op)
Fallback fold_left using range-based for loop.
Definition ah-ranges.H:824
bool ranges_none_of(const Container &c, Pred &&pred)
Fallback none_of using range-based for loop.
Definition ah-ranges.H:859
bool fallback_none_of(const Container &c, Pred &&pred)
Definition ah-ranges.H:812
bool ranges_any_of(const Container &c, Pred &&pred)
Fallback any_of using range-based for loop.
Definition ah-ranges.H:847
bool ranges_all_of(const Container &c, Pred &&pred)
Fallback all_of using range-based for loop.
Definition ah-ranges.H:835
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:107
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
static StlIterator end(SetType &s)
Create an end iterator for the container.