view_closure.hpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. // Copyright (C) 2022 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_STL_INTERFACES_DETAIL_VIEW_CLOSURE_HPP
  7. #define BOOST_STL_INTERFACES_DETAIL_VIEW_CLOSURE_HPP
  8. #include <boost/stl_interfaces/detail/pipeable_view.hpp>
  9. #include <utility>
  10. namespace boost { namespace stl_interfaces { namespace detail {
  11. template<std::size_t I, typename T>
  12. struct box
  13. {
  14. T value_;
  15. };
  16. template<typename Indices, typename Func, typename... T>
  17. struct view_closure_impl;
  18. template<std::size_t... I, typename Func, typename... T>
  19. struct view_closure_impl<std::index_sequence<I...>, Func, T...>
  20. : box<I, T>...
  21. {
  22. view_closure_impl() = default;
  23. constexpr explicit view_closure_impl(Func, T &&... x) :
  24. box<I, T>{std::move(x)}...
  25. {}
  26. #if BOOST_STL_INTERFACES_USE_CONCEPTS
  27. template<std::ranges::input_range R>
  28. requires std::ranges::viewable_range<R> &&
  29. std::invocable<Func, R, T &...> &&
  30. std::ranges::view<std::invoke_result_t<Func, R, T &...>>
  31. constexpr auto operator()(R && r) &
  32. #else
  33. template<typename R>
  34. constexpr auto operator()(R && r) & -> decltype(
  35. Func{}((R &&) r, std::declval<box<I, T> &>().value_...))
  36. #endif
  37. {
  38. return Func{}((R &&) r, static_cast<box<I, T> &>(*this).value_...);
  39. }
  40. #if BOOST_STL_INTERFACES_USE_CONCEPTS
  41. template<std::ranges::input_range R>
  42. requires std::ranges::viewable_range<R> &&
  43. std::invocable<Func, R, T const &...> &&
  44. std::ranges::view<std::invoke_result_t<Func, R, T const &...>>
  45. constexpr auto operator()(R && r) const &
  46. #else
  47. template<typename R>
  48. constexpr auto operator()(R && r) const & -> decltype(
  49. Func{}((R &&) r, std::declval<box<I, T> const &>().value_...))
  50. #endif
  51. {
  52. return Func{}(
  53. (R &&) r, static_cast<box<I, T> const &>(*this).value_...);
  54. }
  55. #if BOOST_STL_INTERFACES_USE_CONCEPTS
  56. template<std::ranges::input_range R>
  57. requires std::ranges::viewable_range<R> &&
  58. std::invocable<Func, R, T...> &&
  59. std::ranges::view<std::invoke_result_t<Func, R, T...>>
  60. constexpr auto operator()(R && r) &&
  61. #else
  62. template<typename R>
  63. constexpr auto operator()(R && r) && -> decltype(
  64. Func{}((R &&) r, std::declval<box<I, T> &&>().value_...))
  65. #endif
  66. {
  67. return Func{}((R &&) r, static_cast<box<I, T> &&>(*this).value_...);
  68. }
  69. };
  70. #if BOOST_STL_INTERFACES_USE_CONCEPTS
  71. template<std::semiregular Func, std::copy_constructible... T>
  72. #else
  73. template<typename Func, typename... T>
  74. #endif
  75. struct view_closure
  76. : pipeable<view_closure<Func, T...>>,
  77. view_closure_impl<std::index_sequence_for<T...>, Func, T...>
  78. {
  79. using base_type =
  80. view_closure_impl<std::index_sequence_for<T...>, Func, T...>;
  81. view_closure() = default;
  82. constexpr explicit view_closure(Func func, T &&... x) :
  83. base_type{func, std::move(x)...}
  84. {}
  85. };
  86. #if defined(__cpp_deduction_guides)
  87. template<typename Func, typename... T>
  88. view_closure(Func, T...) -> view_closure<Func, T...>;
  89. #endif
  90. }}}
  91. #endif