You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.6KB

  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. namespace ranges
  22. {
  23. /// \addtogroup group-functional
  24. /// @{
  25. template<typename Second, typename First>
  26. struct composed
  27. {
  28. private:
  29. RANGES_NO_UNIQUE_ADDRESS
  30. First first_;
  31. RANGES_NO_UNIQUE_ADDRESS
  32. Second second_;
  33. // clang-format off
  34. template<typename A, typename B, typename... Ts>
  35. static auto CPP_auto_fun(do_)(A &a, B &b, std::false_type, Ts &&... ts)
  36. (
  37. return invoke(b, invoke(a, (Ts &&) ts...))
  38. )
  39. template<typename A, typename B, typename... Ts>
  40. static auto CPP_auto_fun(do_)(A &a, B &b, std::true_type, Ts &&... ts)
  41. (
  42. return (invoke(a, (Ts &&) ts...), invoke(b))
  43. )
  44. // clang-format on
  45. public
  46. : //
  47. composed() = default;
  48. composed(Second second, First first)
  49. : first_(std::move(first))
  50. , second_(std::move(second))
  51. {}
  52. // clang-format off
  53. template<typename... Ts>
  54. auto CPP_auto_fun(operator())(Ts &&... ts)
  55. (
  56. return composed::do_(first_,
  57. second_,
  58. std::is_void<invoke_result_t<First &, Ts...>>{},
  59. (Ts &&) ts...)
  60. )
  61. template<typename... Ts>
  62. auto CPP_auto_fun(operator())(Ts &&... ts)(const)
  63. (
  64. return composed::do_((First const &)first_,
  65. (Second const &)second_,
  66. std::is_void<invoke_result_t<First const &, Ts...>>{},
  67. (Ts &&) ts...)
  68. )
  69. // clang-format on
  70. };
  71. struct compose_fn
  72. {
  73. template<typename Second, typename First>
  74. composed<Second, First> operator()(Second second, First first) const
  75. {
  76. return {std::move(second), std::move(first)};
  77. }
  78. };
  79. /// \ingroup group-functional
  80. /// \sa `compose_fn`
  81. RANGES_INLINE_VARIABLE(compose_fn, compose)
  82. /// @}
  83. } // namespace ranges
  84. #endif