17 #ifndef OPENKALMAN_COMPATIBILITY_VIEWS_TO_HPP 18 #define OPENKALMAN_COMPATIBILITY_VIEWS_TO_HPP 27 #if __cpp_lib_ranges_to_container >= 202202L 28 using std::ranges::to;
36 template<
typename Adaptor,
typename...Args>
37 concept adaptor_invocable = requires { std::declval<Adaptor>()(declval<Args>()...); };
39 template<
typename Adaptor,
typename = void,
typename...Args>
42 template<
typename Adaptor,
typename...Args>
46 template<
typename Adaptor,
typename...Args>
51 template<
typename Adaptor,
typename...Args>
55 template<
typename Adaptor,
typename...Args>
58 template<
typename...Ts>
60 Partial(
int, Ts&&...args) : m_args(std::forward<Ts>(args)...) {}
64 template<
typename Range> requires adaptor_invocable<Adaptor, Range&&,
const Args&...>
66 template<
typename Range, std::enable_if_t<adaptor_invocable<Adaptor, Range&&,
const Args&...>,
int> = 0>
69 operator()(Range&& r)
const &
71 auto forwarder = [&r] (
const auto&...args) {
return Adaptor{}(std::forward<Range>(r), args...); };
77 template<
typename Range> requires adaptor_invocable<Adaptor, Range, Args...>
79 template<
typename Range, std::enable_if_t<adaptor_invocable<Adaptor, Range, Args...>,
int> = 0>
82 operator()(Range&& r) &&
84 auto forwarder = [&r] (
auto&... args) {
return Adaptor{}(std::forward<Range>(r), std::move(args)...); };
89 template<
typename Range>
91 operator()(Range&& r)
const && =
delete;
95 tuple<Args...> m_args;
100 template<
typename Adaptor,
typename Arg>
103 template<
typename Tp>
105 Partial(
int, Tp&& arg) : m_arg(std::forward<Tp>(arg)) {}
108 #ifdef __cpp_concepts 109 template<
typename Range> requires adaptor_invocable<Adaptor, Range, const Arg&>
111 template<
typename Range, std::enable_if_t<adaptor_invocable<Adaptor, Range, const Arg&>,
int> = 0>
114 operator()(Range&& r)
const & {
return Adaptor{}(std::forward<Range>(r), m_arg); }
117 #ifdef __cpp_concepts 118 template<
typename Range> requires adaptor_invocable<Adaptor, Range, Arg>
120 template<
typename Range, std::enable_if_t<adaptor_invocable<Adaptor, Range, Arg>,
int> = 0>
123 operator()(Range&& r) && {
return Adaptor{}(std::forward<Range>(r), std::move(m_arg)); }
126 template<
typename Range>
128 operator()(Range&& r)
const && =
delete;
136 #ifdef __cpp_lib_ranges 137 template<
typename Container>
138 inline constexpr
bool reservable_container = std::ranges::sized_range<Container> and
139 requires(Container& c, std::ranges::range_size_t<Container> n)
142 { c.capacity() } -> std::same_as<decltype(n)>;
143 { c.max_size() } -> std::same_as<decltype(n)>;
146 template<
typename Cont,
typename Range>
147 inline constexpr
bool toable = requires {
148 requires (not std::ranges::input_range<Cont> or
149 std::convertible_to<std::ranges::range_reference_t<Range>, std::ranges::range_value_t<Cont>>);
152 template<
typename T,
typename =
void,
typename =
void>
158 std::is_same_v<decltype(std::declval<T&>().capacity()), stdex::ranges::range_size_t<T>> and
159 std::is_same_v<decltype(std::declval<T&>().max_size()), stdex::ranges::range_size_t<T>>>>
162 template<
typename Container>
163 inline constexpr
bool reservable_container =
166 template<
typename Range,
typename =
void>
169 template<
typename Cont>
170 struct toable1_impl<Cont, std::enable_if_t<not stdex::ranges::input_range<Cont>>> : std::true_type {};
172 template<
typename Cont,
typename Range,
typename =
void>
175 template<
typename Cont,
typename Range>
177 stdex::convertible_to<stdex::ranges::range_reference_t<Range>, stdex::ranges::range_value_t<Cont>>>> : std::true_type {};
179 template<
typename Cont,
typename Range>
182 #ifndef __cpp_concepts 183 template<
typename C,
typename I,
typename =
void>
186 template<
typename C,
typename I>
187 struct can_emplace_back<C, I, std::void_t<decltype(std::declval<C&>().emplace_back(*std::declval<I&>()))>>
191 template<
typename C,
typename I,
typename =
void>
194 template<
typename C,
typename I>
195 struct can_push_back<C, I, std::void_t<decltype(std::declval<C&>().push_back(*std::declval<I&>()))>>
199 template<
typename C,
typename I,
typename =
void>
202 template<
typename C,
typename I>
203 struct can_emplace<C, I, std::void_t<decltype(std::declval<C&>().emplace(std::declval<C&>().end(), *std::declval<I&>()))>>
208 #ifdef __cpp_lib_ranges 209 template<
typename Cont, std::ranges::input_range Rg,
typename...Args> requires (not std::ranges::view<Cont>)
211 template<
typename Cont,
typename Rg,
typename...Args, std::enable_if_t<
212 stdex::ranges::input_range<Rg> and not stdex::ranges::view<Cont>,
int> = 0>
215 to [[nodiscard]] (Rg&& r, Args&&... args)
217 static_assert(not std::is_const_v<Cont> and not std::is_volatile_v<Cont>);
218 static_assert(std::is_class_v<Cont>);
220 if constexpr (toable<Cont, Rg>)
222 if constexpr (stdex::constructible_from<Cont, Rg, Args...>)
224 return Cont(std::forward<Rg>(r), std::forward<Args>(args)...);
226 else if constexpr (input_iterator<Rg> and stdex::ranges::common_range<Rg> and
227 stdex::constructible_from<Cont, stdex::ranges::iterator_t<Rg>, stdex::ranges::sentinel_t<Rg>, Args...>)
229 return Cont(stdex::ranges::begin(r), stdex::ranges::end(r), std::forward<Args>(args)...);
233 static_assert(stdex::constructible_from<Cont, Args...>);
234 Cont c(std::forward<Args>(args)...);
235 if constexpr (stdex::ranges::sized_range<Rg> and reservable_container<Cont>)
237 auto it = stdex::ranges::begin(r);
238 const auto sent = stdex::ranges::end(r);
241 #ifdef __cpp_concepts 242 if constexpr (requires { c.emplace_back(*it); }) c.emplace_back(*it);
243 else if constexpr (requires { c.push_back(*it); }) c.push_back(*it);
244 else if constexpr (requires { c.emplace(c.end(), *it); }) c.emplace(c.end(), *it);
248 else if constexpr (
can_emplace<decltype(c), decltype(it)>::
value) c.emplace(c.end(), *it);
250 else c.insert(c.end(), *it);
258 static_assert(stdex::ranges::input_range<stdex::ranges::range_reference_t<Rg>>);
259 return to<Cont>(
ref_view(r) | stdex::ranges::views::transform(
260 [](
auto&& elem) {
return to<stdex::ranges::range_value_t<Cont>>(std::forward<decltype(elem)>(elem)); }), std::forward<Args>(args)...);
265 template<
typename Rg>
268 using iterator_category = std::input_iterator_tag;
269 using value_type = stdex::ranges::range_value_t<Rg>;
270 using difference_type = std::ptrdiff_t;
271 using pointer = std::add_pointer_t<stdex::ranges::range_reference_t<Rg>>;
272 using reference = stdex::ranges::range_reference_t<Rg>;
273 reference operator*()
const;
274 pointer operator->()
const;
280 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
281 using DeduceExpr1 = decltype(Cont(std::declval<Rg>(), std::declval<Args>()...));
283 #ifdef __cpp_concepts 284 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
285 concept can_DeduceExpr1 = requires requires {
typename DeduceExpr1<Cont, Rg, Args...>; };
287 template<
template<
typename...>
typename Cont,
typename Rg,
typename = void,
typename... Args>
290 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
291 struct can_DeduceExpr1_impl<Cont, Rg, std::void_t<DeduceExpr1<Cont, Rg, Args...>>, Args...> : std::true_type {};
293 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
298 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
301 #ifdef __cpp_concepts 302 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
303 concept can_DeduceExpr3 = requires requires {
typename DeduceExpr3<Cont, Rg, Args...>; };
305 template<
template<
typename...>
typename Cont,
typename Rg,
typename = void,
typename... Args>
308 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
309 struct can_DeduceExpr3_impl<Cont, Rg, std::void_t<DeduceExpr3<Cont, Rg, Args...>>, Args...> : std::true_type {};
311 template<
template<
typename...>
typename Cont,
typename Rg,
typename... Args>
316 #ifdef __cpp_concepts 317 template<
template<
typename...>
typename Cont, std::ranges::input_range Rg,
typename...Args>
319 template<
template<
typename...>
typename Cont,
typename Rg,
typename...Args, std::enable_if_t<stdex::ranges::input_range<Rg>,
int> = 0>
322 to [[nodiscard]] (Rg&& r, Args&&... args)
324 if constexpr (can_DeduceExpr1<Cont, Rg, Args...>)
325 return to<DeduceExpr1<Cont, Rg, Args...>>(std::forward<Rg>(r), std::forward<Args>(args)...);
326 else if constexpr (can_DeduceExpr3<Cont, Rg, Args...>)
327 return to<DeduceExpr3<Cont, Rg, Args...>>(std::forward<Rg>(r), std::forward<Args>(args)...);
329 static_assert(
false,
"Cannot deduce container specialization");
333 template<
typename Cont>
336 #ifdef __cpp_concepts 337 template<
typename Range,
typename...Args> requires requires { to<Cont>(std::declval<Range&&>(), std::declval<Args&&>()...); }
339 template<
typename Range,
typename...Args,
typename = std::void_t<decltype(to<Cont>(std::declval<Range&&>(), std::declval<Args&&>()...))>>
342 operator()(Range&& r, Args&&... args)
const 344 return to<Cont>(std::forward<Range>(r), std::forward<Args>(args)...);
349 #ifdef __cpp_concepts 350 template<
typename Cont,
typename... Args> requires (not stdex::ranges::view<Cont>)
352 template<
typename Cont,
typename...Args, std::enable_if_t<not stdex::ranges::view<Cont>,
int> = 0>
355 to [[nodiscard]] (Args&&... args)
361 template<
template<
typename...>
typename Cont>
364 #ifdef __cpp_concepts 365 template<
typename Range,
typename...Args> requires requires { to<Cont>(std::declval<Range&&>(), std::declval<Args&&>()...); }
367 template<
typename Range,
typename...Args,
typename = std::void_t<decltype(to<Cont>(std::declval<Range&&>(), std::declval<Args&&>()...))>>
370 operator()(Range&& r, Args&&...args)
const 372 return to<Cont>(std::forward<Range>(r), std::forward<Args>(args)...);
377 template<
template<
typename...>
typename Cont,
typename...Args>
379 to [[nodiscard]] (Args&&...args)
constexpr bool value
T is a fixed or dynamic value that is reducible to a number.
Definition: value.hpp:45
decltype(auto) constexpr apply(F &&f, T &&t)
A generalization of std::apply.
Definition: apply.hpp:49
Definitions relating to the availability of c++ language features.
Definition: common.hpp:200
constexpr bool size
T is either an index representing a size, or unbounded_size_t, which indicates that the size is unbou...
Definition: size.hpp:65
Definition: range_adaptor_closure.hpp:34
Definition: ref_view.hpp:33