17 #ifndef OPENKALMAN_COMPATIBILITY_VIEWS_TO_HPP 18 #define OPENKALMAN_COMPATIBILITY_VIEWS_TO_HPP 20 #if __cpp_lib_ranges_to_container < 202202L 22 #ifdef __cpp_lib_ranges 39 template<
typename Adaptor,
typename...Args>
40 concept adaptor_invocable = requires { std::declval<Adaptor>()(declval<Args>()...); };
42 template<
typename Adaptor,
typename = void,
typename...Args>
45 template<
typename Adaptor,
typename...Args>
49 template<
typename Adaptor,
typename...Args>
54 template<
typename Adaptor,
typename...Args>
58 template<
typename Adaptor,
typename...Args>
61 template<
typename...Ts>
63 Partial(
int, Ts&&...args) : m_args(std::forward<Ts>(args)...) {}
67 template<
typename Range> requires adaptor_invocable<Adaptor, Range&&,
const Args&...>
69 template<
typename Range, std::enable_if_t<adaptor_invocable<Adaptor, Range&&,
const Args&...>,
int> = 0>
72 operator()(Range&& r)
const &
74 auto forwarder = [&r] (
const auto&...args) {
return Adaptor{}(std::forward<Range>(r), args...); };
75 return std::apply(forwarder, m_args);
80 template<
typename Range> requires adaptor_invocable<Adaptor, Range, Args...>
82 template<
typename Range, std::enable_if_t<adaptor_invocable<Adaptor, Range, Args...>,
int> = 0>
85 operator()(Range&& r) &&
87 auto forwarder = [&r] (
auto&... args) {
return Adaptor{}(std::forward<Range>(r), std::move(args)...); };
88 return std::apply(forwarder, m_args);
92 template<
typename Range>
94 operator()(Range&& r)
const && =
delete;
98 tuple<Args...> m_args;
103 template<
typename Adaptor,
typename Arg>
106 template<
typename Tp>
108 Partial(
int, Tp&& arg) : m_arg(std::forward<Tp>(arg)) {}
111 #ifdef __cpp_concepts 112 template<
typename Range> requires adaptor_invocable<Adaptor, Range, const Arg&>
114 template<
typename Range, std::enable_if_t<adaptor_invocable<Adaptor, Range, const Arg&>,
int> = 0>
117 operator()(Range&& r)
const & {
return Adaptor{}(std::forward<Range>(r), m_arg); }
120 #ifdef __cpp_concepts 121 template<
typename Range> requires adaptor_invocable<Adaptor, Range, Arg>
123 template<
typename Range, std::enable_if_t<adaptor_invocable<Adaptor, Range, Arg>,
int> = 0>
126 operator()(Range&& r) && {
return Adaptor{}(std::forward<Range>(r), std::move(m_arg)); }
129 template<
typename Range>
131 operator()(Range&& r)
const && =
delete;
139 #ifdef __cpp_lib_ranges 140 template<
typename Container>
141 inline constexpr
bool reservable_container = std::ranges::sized_range<Container> and
142 requires(Container& c, std::ranges::range_size_t<Container> n)
145 { c.capacity() } -> std::same_as<decltype(n)>;
146 { c.max_size() } -> std::same_as<decltype(n)>;
149 template<
typename Cont,
typename Range>
150 inline constexpr
bool toable = requires {
151 requires (not std::ranges::input_range<Cont> or
152 std::convertible_to<std::ranges::range_reference_t<Range>, std::ranges::range_value_t<Cont>>);
155 template<
typename T,
typename =
void,
typename =
void>
161 std::is_same_v<decltype(std::declval<T&>().capacity()), ranges::range_size_t<T>> and
162 std::is_same_v<decltype(std::declval<T&>().max_size()), ranges::range_size_t<T>>>>
165 template<
typename Container>
166 inline constexpr
bool reservable_container =
169 template<
typename Range,
typename =
void>
172 template<
typename Cont>
173 struct toable1_impl<Cont, std::enable_if_t<not ranges::input_range<Cont>>> : std::true_type {};
175 template<
typename Cont,
typename Range,
typename =
void>
178 template<
typename Cont,
typename Range>
180 std::is_convertible_v<ranges::range_reference_t<Range>, ranges::range_value_t<Cont>>>> : std::true_type {};
182 template<
typename Cont,
typename Range>
185 #ifndef __cpp_concepts 186 template<
typename C,
typename I,
typename =
void>
189 template<
typename C,
typename I>
190 struct can_emplace_back<C, I, std::void_t<decltype(std::declval<C&>().emplace_back(*std::declval<I&>()))>>
194 template<
typename C,
typename I,
typename =
void>
197 template<
typename C,
typename I>
198 struct can_push_back<C, I, std::void_t<decltype(std::declval<C&>().push_back(*std::declval<I&>()))>>
202 template<
typename C,
typename I,
typename =
void>
205 template<
typename C,
typename I>
206 struct can_emplace<C, I, std::void_t<decltype(std::declval<C&>().emplace(std::declval<C&>().end(), *std::declval<I&>()))>>
211 #ifdef __cpp_lib_ranges 212 template<
typename Cont, std::ranges::input_range Rg,
typename...Args> requires (not std::ranges::view<Cont>)
214 template<
typename Cont,
typename Rg,
typename...Args, std::enable_if_t<
215 ranges::input_range<Rg> and not ranges::view<Cont>,
int> = 0>
218 to [[nodiscard]] (Rg&& r, Args&&... args)
220 static_assert(not std::is_const_v<Cont> and not std::is_volatile_v<Cont>);
221 static_assert(std::is_class_v<Cont>);
223 if constexpr (toable<Cont, Rg>)
225 if constexpr (std::is_constructible_v<Cont, Rg, Args...>)
227 return Cont(std::forward<Rg>(r), std::forward<Args>(args)...);
229 else if constexpr (input_iterator<Rg> and ranges::common_range<Rg> and
230 std::is_constructible_v<Cont, ranges::iterator_t<Rg>, ranges::sentinel_t<Rg>, Args...>)
232 return Cont(ranges::begin(r), ranges::end(r), std::forward<Args>(args)...);
236 static_assert(std::is_constructible_v<Cont, Args...>);
237 Cont c(std::forward<Args>(args)...);
238 if constexpr (ranges::sized_range<Rg> and reservable_container<Cont>)
239 c.reserve(
static_cast<ranges::range_size_t<Cont>
>(
ranges::size(r)));
240 auto it = ranges::begin(r);
241 const auto sent = ranges::end(r);
244 #ifdef __cpp_concepts 245 if constexpr (requires { c.emplace_back(*it); }) c.emplace_back(*it);
246 else if constexpr (requires { c.push_back(*it); }) c.push_back(*it);
247 else if constexpr (requires { c.emplace(c.end(), *it); }) c.emplace(c.end(), *it);
251 else if constexpr (
can_emplace<decltype(c), decltype(it)>::
value) c.emplace(c.end(), *it);
253 else c.insert(c.end(), *it);
261 static_assert(ranges::input_range<ranges::range_reference_t<Rg>>);
262 return to<Cont>(
ref_view(r) | ranges::views::transform(
263 [](
auto&& elem) {
return to<ranges::range_value_t<Cont>>(std::forward<decltype(elem)>(elem)); }), std::forward<Args>(args)...);
268 template<
typename Rg>
271 using iterator_category = std::input_iterator_tag;
272 using value_type = ranges::range_value_t<Rg>;
273 using difference_type = std::ptrdiff_t;
274 using pointer = std::add_pointer_t<ranges::range_reference_t<Rg>>;
275 using reference = ranges::range_reference_t<Rg>;
276 reference operator*()
const;
277 pointer operator->()
const;
283 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
284 using DeduceExpr1 = decltype(Cont(std::declval<Rg>(), std::declval<Args>()...));
286 #ifdef __cpp_concepts 287 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
288 concept can_DeduceExpr1 = requires requires {
typename DeduceExpr1<Cont, Rg, Args...>; };
290 template<
template<
typename...>
typename Cont,
typename Rg,
typename = void,
typename... Args>
293 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
294 struct can_DeduceExpr1_impl<Cont, Rg, std::void_t<DeduceExpr1<Cont, Rg, Args...>>, Args...> : std::true_type {};
296 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
301 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
304 #ifdef __cpp_concepts 305 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
306 concept can_DeduceExpr3 = requires requires {
typename DeduceExpr3<Cont, Rg, Args...>; };
308 template<
template<
typename...>
typename Cont,
typename Rg,
typename = void,
typename... Args>
311 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
312 struct can_DeduceExpr3_impl<Cont, Rg, std::void_t<DeduceExpr3<Cont, Rg, Args...>>, Args...> : std::true_type {};
314 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
319 #ifdef __cpp_concepts 320 template<
template<
typename...>
typename Cont, std::ranges::input_range Rg,
typename...Args>
322 template<
template<
typename...>
typename Cont,
typename Rg,
typename...Args, std::enable_if_t<ranges::input_range<Rg>,
int> = 0>
325 to [[nodiscard]] (Rg&& r, Args&&... args)
327 if constexpr (can_DeduceExpr1<Cont, Rg, Args...>)
328 return to<DeduceExpr1<Cont, Rg, Args...>>(std::forward<Rg>(r), std::forward<Args>(args)...);
329 else if constexpr (can_DeduceExpr3<Cont, Rg, Args...>)
330 return to<DeduceExpr3<Cont, Rg, Args...>>(std::forward<Rg>(r), std::forward<Args>(args)...);
332 static_assert(
false,
"Cannot deduce container specialization");
336 template<
typename Cont>
339 #ifdef __cpp_concepts 340 template<
typename Range,
typename...Args> requires requires { to<Cont>(std::declval<Range&&>(), std::declval<Args&&>()...); }
342 template<
typename Range,
typename...Args,
typename = std::void_t<decltype(to<Cont>(std::declval<Range&&>(), std::declval<Args&&>()...))>>
345 operator()(Range&& r, Args&&... args)
const 347 return to<Cont>(std::forward<Range>(r), std::forward<Args>(args)...);
352 #ifdef __cpp_concepts 353 template<
typename Cont,
typename... Args> requires (not ranges::view<Cont>)
355 template<
typename Cont,
typename...Args, std::enable_if_t<not ranges::view<Cont>,
int> = 0>
358 to [[nodiscard]] (Args&&... args)
364 template<
template<
typename...>
typename Cont>
367 #ifdef __cpp_concepts 368 template<
typename Range,
typename...Args> requires requires { to<Cont>(std::declval<Range&&>(), std::declval<Args&&>()...); }
370 template<
typename Range,
typename...Args,
typename = std::void_t<decltype(to<Cont>(std::declval<Range&&>(), std::declval<Args&&>()...))>>
373 operator()(Range&& r, Args&&...args)
const 375 return to<Cont>(std::forward<Range>(r), std::forward<Args>(args)...);
380 template<
template<
typename...>
typename Cont,
typename...Args>
382 to [[nodiscard]] (Args&&...args)
395 #endif //OPENKALMAN_COMPATIBILITY_VIEWS_TO_HPP
Definition: tuple_reverse.hpp:103
constexpr bool value
T is numerical value or is reducible to a numerical value.
Definition: value.hpp:31
Definition: range-access.hpp:25
Definition: ref_view.hpp:32
constexpr bool size
T is either an index representing a size, or void which represents that there is no size...
Definition: size.hpp:32
Definition: range_adaptor_closure.hpp:35
Definitions implementing features of the c++ ranges library for compatibility.