compose.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_FUNCTIONAL_COMPOSE_HPP
  14. #define RANGES_V3_FUNCTIONAL_COMPOSE_HPP
  15. #include <type_traits>
  16. #include <utility>
  17. #include <concepts/concepts.hpp>
  18. #include <range/v3/detail/config.hpp>
  19. #include <range/v3/functional/invoke.hpp>
  20. #include <range/v3/utility/static_const.hpp>
  21. #include <range/v3/detail/prologue.hpp>
  22. namespace ranges
  23. {
  24. /// \addtogroup group-functional
  25. /// @{
  26. template<typename Second, typename First>
  27. struct composed
  28. {
  29. private:
  30. RANGES_NO_UNIQUE_ADDRESS
  31. First first_;
  32. RANGES_NO_UNIQUE_ADDRESS
  33. Second second_;
  34. // clang-format off
  35. template<typename A, typename B, typename... Ts>
  36. static constexpr auto //
  37. CPP_auto_fun(do_)(A &&a, B &&b, std::false_type, Ts &&... ts)
  38. (
  39. return invoke((B &&) b, invoke((A &&) a, (Ts &&) ts...))
  40. )
  41. template<typename A, typename B, typename... Ts>
  42. static constexpr auto CPP_auto_fun(do_)(A &&a, B &&b, std::true_type, Ts &&... ts)
  43. (
  44. return (invoke((A &&) a, (Ts &&) ts...), invoke((B &&) b))
  45. )
  46. public:
  47. composed() = default;
  48. // clang-format on
  49. constexpr composed(Second second, First first)
  50. : first_(std::move(first))
  51. , second_(std::move(second))
  52. {}
  53. // clang-format off
  54. template<typename... Ts>
  55. constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(mutable &)
  56. (
  57. return composed::do_(first_,
  58. second_,
  59. std::is_void<invoke_result_t<First &, Ts...>>{},
  60. (Ts &&) ts...)
  61. )
  62. template<typename... Ts>
  63. constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(const &)
  64. (
  65. return composed::do_((First const &)first_,
  66. (Second const &)second_,
  67. std::is_void<invoke_result_t<First const &, Ts...>>{},
  68. (Ts &&) ts...)
  69. )
  70. template<typename... Ts>
  71. constexpr auto CPP_auto_fun(operator())(Ts &&... ts)(mutable &&)
  72. (
  73. return composed::do_((First &&)first_,
  74. (Second &&)second_,
  75. std::is_void<invoke_result_t<First &&, Ts...>>{},
  76. (Ts &&) ts...)
  77. )
  78. // clang-format on
  79. };
  80. struct compose_fn
  81. {
  82. template<typename Second, typename First>
  83. constexpr composed<Second, First> operator()(Second second, First first) const
  84. {
  85. return {std::move(second), std::move(first)};
  86. }
  87. };
  88. /// \ingroup group-functional
  89. /// \sa `compose_fn`
  90. RANGES_INLINE_VARIABLE(compose_fn, compose)
  91. /// @}
  92. } // namespace ranges
  93. #include <range/v3/detail/epilogue.hpp>
  94. #endif