libzypp: zypp-core/ng/base/ranges.h Source File

libzypp 17.38.14

ranges.h
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
28#ifndef ZYPPNG_BASE_RANGES_H
29#define ZYPPNG_BASE_RANGES_H
30
31#include <iterator>
32#include <type_traits>
33#include <zypp-core/ng/meta/type_traits.h>
34
35// ---------------------------------------------------------------------------
36// 1. Pull the polyfill backend into an internal namespace.
37// Consumers never touch _detail::polyfill directly.
38// ---------------------------------------------------------------------------
39
40#if defined(__cpp_lib_ranges) && __cpp_lib_ranges >= 201911L && !defined(ZYPPNG_FORCE_NANORANGE)
41# include <ranges>
42 namespace zyppng::_detail { namespace polyfill = std::ranges; }
43#else
44# include <nanorange/nanorange.hpp>
45 namespace zyppng::_detail { namespace polyfill = nano::ranges; }
46#endif
47
48// ---------------------------------------------------------------------------
49// 2. zyppng::ranges — the single public interface.
50//
51// We define zyppng::ranges as a true namespace (not an alias) so that
52// we can extend it with our own additions (e.g. ranges::to) while still
53// exposing the full polyfill API via using-declarations.
54// ---------------------------------------------------------------------------
55
56 namespace zyppng::ranges {
57
58 // Expose the full polyfill API: all algorithms, views, concepts.
59 using namespace ::zyppng::_detail::polyfill;
60
61 // views sub-namespace: zyppng::ranges::views::filter etc.
62 namespace views = ::zyppng::_detail::polyfill::views;
63
64} // namespace zyppng::ranges
65
66// ---------------------------------------------------------------------------
67// 3. ranges::to<Container>() — C++23 backport for C++17
68//
69// std::ranges::to is C++23 and absent from both std::ranges (C++20) and
70// nanorange. We provide our own implementation here so that all range
71// pipelines can terminate with a uniform | zyppng::ranges::to<T>() call
72// regardless of compiler baseline.
73// ---------------------------------------------------------------------------
74
75namespace zyppng::ranges {
76
77 namespace detail {
78
79 // Detector ops — uses the detector idiom from type_traits.h
80 template<typename T>
81 using reserve_op = decltype( std::declval<T&>().reserve( std::declval<std::size_t>() ) );
82
83 template<typename T>
84 using size_op = decltype( std::declval<const T&>().size() );
85
86 // Reserve capacity upfront if both Container and Range support it.
87 template<typename Container, typename Range>
88 void maybe_reserve( Container & c, const Range & r )
89 {
90 if constexpr ( std::is_detected_v<reserve_op, Container>
91 && std::is_detected_v<size_op, Range> )
92 c.reserve( r.size() );
93 }
94
95} // namespace detail
96
108 template<typename Container, typename Range>
109 Container to( Range && range )
110 {
111 Container result;
112 detail::maybe_reserve( result, range );
113
114 // std::is_rvalue_reference<Range&&> recovers the value category via
115 // reference collapsing: lvalue -> Range = T& -> Range&& = T& -> false
116 // rvalue -> Range = T -> Range&& = T&& -> true
117 if constexpr ( std::is_rvalue_reference<Range&&>::value ) {
118 std::move( std::begin(range), std::end(range),
119 std::inserter(result, std::end(result)) );
120 } else {
121 std::copy( std::begin(range), std::end(range),
122 std::inserter(result, std::end(result)) );
123 }
124 return result;
125 }
126
127 // Pipe adaptor: range | zyppng::ranges::to<Container>()
128 template<typename Container>
129 struct to_fn {
130 template<typename Range>
131 friend Container operator|( Range && range, to_fn )
132 {
133 return zyppng::ranges::to<Container>( std::forward<Range>(range) );
134 }
135 };
136
137 template<typename Container>
138 to_fn<Container> to() { return {}; }
139
140} // namespace zyppng::ranges
141
142#endif // ZYPPNG_BASE_RANGES_H
std::is_detected_v
constexpr bool is_detected_v
Definition type_traits.h:57
zyppng::_detail
Definition ranges.h:45
zyppng::ranges::detail
Definition ranges.h:77
zyppng::ranges::detail::size_op
decltype(std::declval< const T & >().size()) size_op
Definition ranges.h:84
zyppng::ranges::detail::maybe_reserve
void maybe_reserve(Container &c, const Range &r)
Definition ranges.h:88
zyppng::ranges::detail::reserve_op
decltype(std::declval< T & >().reserve(std::declval< std::size_t >())) reserve_op
Definition ranges.h:81
zyppng::ranges
Definition ranges.h:56
zyppng::ranges::to
to_fn< Container > to()
Definition ranges.h:138
zyppng::ranges::to
Container to(Range &&range)
Convert any range into a Container.
Definition ranges.h:109
zypp::Range
Definition Range.h:35
zyppng::ranges::to_fn
Definition ranges.h:129
zyppng::ranges::to_fn::operator|
friend Container operator|(Range &&range, to_fn)
Definition ranges.h:131
type_traits.h