Line data Source code
1 : // Copyright (c) 2022-2026 The Dash Core developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : 5 : #ifndef BITCOIN_UTIL_STD23_H 6 : #define BITCOIN_UTIL_STD23_H 7 : 8 : #include <algorithm> 9 : #include <functional> 10 : #include <iterator> 11 : #include <ranges> 12 : #include <type_traits> 13 : #include <utility> 14 : 15 : namespace std23 { 16 : #if __cplusplus >= 202302L 17 : using std::to_underlying; 18 : #else 19 : /** 20 : * @tparam E enumeration type, automatically deduced 21 : * @param e the enumerated value to convert 22 : * @return the underlying value in base type 23 : */ 24 : template <typename E> 25 29971 : [[nodiscard]] inline constexpr std::underlying_type_t<E> to_underlying(E e) noexcept 26 : { 27 29971 : return static_cast<std::underlying_type_t<E>>(e); 28 : } 29 : #endif // __cplusplus >= 202302L 30 : namespace ranges { 31 : #if __cplusplus >= 202302L 32 : using std::ranges::contains; 33 : using std::ranges::fold_left; 34 : #else 35 : /** 36 : * @tparam R range type, automatically deduced 37 : * @tparam T value type to search for, automatically deduced 38 : * @tparam Proj projection type 39 : * @param range the range to search in 40 : * @param value the value to search for 41 : * @param proj optional projection to apply to elements before comparison 42 : * @return true if the range contains the value, false otherwise 43 : * 44 : * @see https://github.com/llvm/llvm-project/blob/llvmorg-22.1.0/libcxx/include/__algorithm/ranges_contains.h 45 : */ 46 : template <typename R, typename T, typename Proj = std::identity> 47 7 : inline constexpr bool contains(R&& range, const T& value, Proj proj = {}) 48 : { 49 7 : return std::ranges::find(std::ranges::begin(range), std::ranges::end(range), value, proj) != std::ranges::end(range); 50 : } 51 : 52 : /** 53 : * @tparam R range type, automatically deduced 54 : * @tparam T initial value type, automatically deduced 55 : * @tparam F binary operation type, automatically deduced 56 : * @param range the range to fold 57 : * @param init the initial value 58 : * @param f binary operation to apply 59 : * @return the result of left-folding the range with f 60 : * 61 : * @see https://github.com/llvm/llvm-project/blob/llvmorg-22.1.0/libcxx/include/__algorithm/ranges_fold.h 62 : */ 63 : template <typename R, typename T, typename F> 64 36473 : inline constexpr auto fold_left(R&& range, T init, F f) 65 : { 66 : using I = decltype(std::ranges::begin(range)); 67 : using U = std::decay_t<std::invoke_result_t<F&, T, std::iter_reference_t<I>>>; 68 : 69 36473 : auto first = std::ranges::begin(range); 70 36473 : auto last = std::ranges::end(range); 71 36473 : if (first == last) { 72 0 : return U(std::move(init)); 73 : } 74 : 75 36473 : U accum = std::invoke(f, std::move(init), *first); 76 182356 : for (++first; first != last; ++first) { 77 145883 : accum = std::invoke(f, std::move(accum), *first); 78 145883 : } 79 36473 : return accum; 80 36473 : } 81 : #endif // __cplusplus >= 202302L 82 : namespace views { 83 : #if __cplusplus >= 202302L 84 : using std::ranges::views::enumerate; 85 : #else 86 : /** 87 : * @tparam T type of iterable, automatically deduced 88 : * @tparam TIter begin of container 89 : * @param iterable an iterable object, can be a temporary 90 : * @return struct containing a size_t index, and it's element in iterable 91 : */ 92 : template <typename T, 93 : typename TIter = decltype(std::begin(std::declval<T>())), 94 : typename = decltype(std::end(std::declval<T>()))> 95 499 : inline constexpr auto enumerate(T && iterable) 96 : { 97 : struct iterator { 98 : size_t i; 99 : TIter iter; 100 1496 : bool operator!=(const iterator& other) const { return iter != other.iter; } 101 997 : void operator++() 102 : { 103 997 : ++i; 104 997 : ++iter; 105 997 : } 106 997 : auto operator*() const { return std::tie(i, *iter); } 107 : }; 108 : struct iterable_wrapper { 109 : T iterable; 110 499 : auto begin() { return iterator{0, std::begin(iterable)}; } 111 499 : auto end() { return iterator{0, std::end(iterable)}; } 112 : }; 113 499 : return iterable_wrapper{std::forward<T>(iterable)}; 114 : } 115 : #endif // __cplusplus >= 202302L 116 : } // namespace views 117 : } // namespace ranges 118 : namespace views { 119 : using namespace std23::ranges::views; 120 : } // namespace views 121 : } // namespace std23 122 : 123 : #endif // BITCOIN_UTIL_STD23_H