libzypp  17.38.7
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>
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 
75 namespace 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
decltype(std::declval< const T & >().size()) size_op
Definition: ranges.h:84
Container to(Range &&range)
Convert any range into a Container.
Definition: ranges.h:109
friend Container operator|(Range &&range, to_fn)
Definition: ranges.h:131
std::ostream & copy(std::istream &from_r, std::ostream &to_r)
Copy istream to ostream.
Definition: IOStream.h:51
void maybe_reserve(Container &c, const Range &r)
Definition: ranges.h:88
decltype(std::declval< T & >().reserve(std::declval< std::size_t >())) reserve_op
Definition: ranges.h:81