|
12 | 12 |
|
13 | 13 | #pragma once
|
14 | 14 |
|
| 15 | +#include <algorithm> |
15 | 16 | #include <concepts>
|
16 | 17 | #include <functional>
|
17 | 18 | #include <iterator>
|
@@ -42,8 +43,7 @@ struct nest_fn
|
42 | 43 | };
|
43 | 44 |
|
44 | 45 | template <class Iter, class Fn>
|
45 |
| -concept fn_constraints = std::is_object_v<Fn> && std::copy_constructible<Fn> && |
46 |
| - std::regular_invocable<Fn const &, std::iter_reference_t<Iter>> && |
| 46 | +concept fn_constraints = std::is_object_v<Fn> && std::regular_invocable<Fn const &, std::iter_reference_t<Iter>> && |
47 | 47 | can_reference<std::invoke_result_t<Fn const &, std::iter_reference_t<Iter>>>;
|
48 | 48 |
|
49 | 49 | } // namespace radr::detail::transform
|
@@ -280,85 +280,98 @@ class transform_sentinel
|
280 | 280 | }
|
281 | 281 | };
|
282 | 282 |
|
283 |
| -inline constexpr auto transform_borrow_impl = |
284 |
| - []<typename UIt, typename USen, typename UCIt, typename UCSen, typename Fn, typename Size>(UIt it, |
285 |
| - USen sen, |
286 |
| - UCIt, |
287 |
| - UCSen, |
288 |
| - Size size, |
289 |
| - Fn fn) |
| 283 | +inline constexpr auto transform_borrow = []<typename URange, typename Fn>(URange && urange, Fn fn) |
290 | 284 | {
|
291 |
| - using iterator_t = transform_iterator<UIt, Fn>; |
292 |
| - using sentinel_t = std::conditional_t<std::same_as<UIt, USen>, iterator_t, transform_sentinel<UIt, USen, Fn>>; |
293 |
| - |
294 |
| - using const_iterator_t = transform_iterator<UCIt, Fn>; |
295 |
| - using const_sentinel_t = |
296 |
| - std::conditional_t<std::same_as<UCIt, UCSen>, const_iterator_t, transform_sentinel<UCIt, UCSen, Fn>>; |
297 |
| - |
298 |
| - static constexpr auto kind = decays_to<Size, not_size> ? borrowing_rad_kind::unsized : borrowing_rad_kind::sized; |
299 |
| - |
300 |
| - using BorrowingRad = borrowing_rad<iterator_t, sentinel_t, const_iterator_t, const_sentinel_t, kind>; |
301 |
| - return BorrowingRad{ |
302 |
| - iterator_t{fn, it}, |
303 |
| - sentinel_t{fn, sen}, |
304 |
| - size |
| 285 | + static_assert(borrowed_mp_range<URange>, "The constraints for radr::transform's underlying range are not met."); |
| 286 | + static_assert(detail::transform::fn_constraints<radr::iterator_t<URange>, Fn> && |
| 287 | + detail::transform::fn_constraints<radr::const_iterator_t<URange>, Fn>, |
| 288 | + "The constraints for radr::transform's functor are not met."); |
| 289 | + |
| 290 | + constexpr auto impl = |
| 291 | + []<typename UIt, typename USen, typename UCIt, typename UCSen, typename Fn_, typename Size>(UIt it, |
| 292 | + USen sen, |
| 293 | + UCIt, |
| 294 | + UCSen, |
| 295 | + Size size, |
| 296 | + Fn_ fn) |
| 297 | + { |
| 298 | + using iterator_t = transform_iterator<UIt, Fn_>; |
| 299 | + using sentinel_t = std::conditional_t<std::same_as<UIt, USen>, iterator_t, transform_sentinel<UIt, USen, Fn>>; |
| 300 | + |
| 301 | + using const_iterator_t = transform_iterator<UCIt, Fn_>; |
| 302 | + using const_sentinel_t = |
| 303 | + std::conditional_t<std::same_as<UCIt, UCSen>, const_iterator_t, transform_sentinel<UCIt, UCSen, Fn_>>; |
| 304 | + |
| 305 | + static constexpr auto kind = |
| 306 | + decays_to<Size, not_size> ? borrowing_rad_kind::unsized : borrowing_rad_kind::sized; |
| 307 | + |
| 308 | + using BorrowingRad = borrowing_rad<iterator_t, sentinel_t, const_iterator_t, const_sentinel_t, kind>; |
| 309 | + return BorrowingRad{ |
| 310 | + iterator_t{fn, it}, |
| 311 | + sentinel_t{fn, sen}, |
| 312 | + size |
| 313 | + }; |
305 | 314 | };
|
306 |
| -}; |
307 | 315 |
|
308 |
| -inline constexpr auto transform_borrow = |
309 |
| - []<borrowed_mp_range URange, std::copy_constructible Fn>(URange && urange, Fn fn) |
310 |
| - requires(detail::transform::fn_constraints<radr::iterator_t<URange>, Fn>) |
311 |
| -{ |
312 |
| - // dispatch between generic case and chained case(s) |
| 316 | + /* dispatch between generic case and chained case(s) */ |
| 317 | + // clang-format off |
313 | 318 | return overloaded{
|
314 |
| - transform_borrow_impl, |
315 |
| - []<typename UIt, typename UCIt, typename UFn, typename Size, typename Fn_>(transform_iterator<UIt, UFn> iter, |
316 |
| - transform_iterator<UIt, UFn> sen, |
317 |
| - transform_iterator<UCIt, UFn> citer, |
318 |
| - transform_iterator<UCIt, UFn> csen, |
319 |
| - Size size, |
320 |
| - Fn_ new_fn) |
| 319 | + /* generic */ |
| 320 | + impl, |
| 321 | + /* nested common */ |
| 322 | + []<typename UIt, typename UCIt, typename UFn, typename Size>( |
| 323 | + transform_iterator<UIt, UFn> iter, |
| 324 | + transform_iterator<UIt, UFn> sen, |
| 325 | + transform_iterator<UCIt, UFn> citer, |
| 326 | + transform_iterator<UCIt, UFn> csen, |
| 327 | + Size size, |
| 328 | + Fn new_fn) |
321 | 329 | {
|
322 |
| - return transform_borrow_impl(std::move(iter).base(), |
323 |
| - std::move(sen).base(), |
324 |
| - std::move(citer).base(), |
325 |
| - std::move(csen).base(), |
326 |
| - size, |
327 |
| - transform::nest_fn{std::move(iter).func(), std::move(new_fn)}); |
| 330 | + return decltype(impl){}(std::move(iter).base(), |
| 331 | + std::move(sen).base(), |
| 332 | + std::move(citer).base(), |
| 333 | + std::move(csen).base(), |
| 334 | + size, |
| 335 | + transform::nest_fn{std::move(iter).func(), std::move(new_fn)}); |
328 | 336 | },
|
329 |
| - []<typename UIt, typename USen, typename UCIt, typename UCSen, typename UFn, typename Size, typename Fn_>( |
| 337 | + /* nested non-common */ |
| 338 | + []<typename UIt, typename USen, typename UCIt, typename UCSen, typename UFn, typename Size>( |
330 | 339 | transform_iterator<UIt, UFn> iter,
|
331 | 340 | transform_sentinel<UIt, USen, UFn> sen,
|
332 | 341 | transform_iterator<UCIt, UFn> citer,
|
333 | 342 | transform_sentinel<UCIt, UCSen, UFn> csen,
|
334 | 343 | Size size,
|
335 |
| - Fn_ new_fn) |
| 344 | + Fn new_fn) |
336 | 345 | {
|
337 |
| - return transform_borrow_impl(std::move(iter).base(), |
338 |
| - std::move(sen).base(), |
339 |
| - std::move(citer).base(), |
340 |
| - std::move(csen).base(), |
341 |
| - size, |
342 |
| - transform::nest_fn{std::move(iter).func(), std::move(new_fn)}); |
| 346 | + return decltype(impl){}(std::move(iter).base(), |
| 347 | + std::move(sen).base(), |
| 348 | + std::move(citer).base(), |
| 349 | + std::move(csen).base(), |
| 350 | + size, |
| 351 | + transform::nest_fn{std::move(iter).func(), std::move(new_fn)}); |
343 | 352 | }}(radr::begin(urange),
|
344 | 353 | radr::end(urange),
|
345 | 354 | radr::cbegin(urange),
|
346 | 355 | radr::cend(urange),
|
347 | 356 | detail::size_or_not(urange),
|
348 | 357 | std::move(fn));
|
| 358 | + // clang-format on |
349 | 359 | };
|
350 | 360 |
|
351 |
| -inline constexpr auto transform_coro = |
352 |
| - []<std::ranges::input_range URange, std::move_constructible Fn>(URange && urange, Fn fn) |
353 |
| - requires(std::invocable<Fn &, std::ranges::range_reference_t<URange>> && |
354 |
| - can_reference<std::invoke_result_t<Fn &, std::ranges::range_reference_t<URange>>>) |
| 361 | +inline constexpr auto transform_coro = []<std::ranges::input_range URange, typename Fn>(URange && urange, Fn fn) |
355 | 362 | {
|
| 363 | + static_assert(std::move_constructible<Fn> && std::invocable<Fn &, std::ranges::range_reference_t<URange>>, |
| 364 | + "The constraints for radr::transform's functor are not met."); |
| 365 | + |
| 366 | + using ref_t = std::invoke_result_t<Fn &, std::ranges::range_reference_t<URange>>; |
| 367 | + static_assert(can_reference<std::invoke_result_t<Fn &, std::ranges::range_reference_t<URange>>>, |
| 368 | + "The constraints for radr::transform's functor are not met."); |
| 369 | + |
356 | 370 | static_assert(!std::is_lvalue_reference_v<URange>, RADR_ASSERTSTRING_RVALUE);
|
357 | 371 | static_assert(std::movable<URange>, RADR_ASSERTSTRING_MOVABLE);
|
358 | 372 |
|
359 | 373 | // we need to create inner functor so that it can take by value
|
360 |
| - return |
361 |
| - [](auto urange_, Fn fn) -> radr::generator<std::invoke_result_t<Fn &, std::ranges::range_reference_t<URange>>> |
| 374 | + return [](auto urange_, Fn fn) -> radr::generator<ref_t, std::remove_cvref_t<ref_t>> |
362 | 375 | {
|
363 | 376 | for (auto && elem : urange_)
|
364 | 377 | co_yield fn(std::forward<decltype(elem)>(elem));
|
|
0 commit comments