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.

133 lines
3.8KB

  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_PIPEABLE_HPP
  14. #define RANGES_V3_FUNCTIONAL_PIPEABLE_HPP
  15. #include <concepts/concepts.hpp>
  16. #include <range/v3/range_fwd.hpp>
  17. #include <range/v3/utility/static_const.hpp>
  18. namespace ranges
  19. {
  20. /// \addtogroup group-functional
  21. /// @{
  22. struct pipeable_base;
  23. template<typename T>
  24. RANGES_INLINE_VAR constexpr bool is_pipeable_v = META_IS_BASE_OF(pipeable_base, T);
  25. template<typename T>
  26. RANGES_INLINE_VAR constexpr bool is_pipeable_v<T &> = META_IS_BASE_OF(pipeable_base,
  27. T);
  28. template<typename T>
  29. RANGES_INLINE_VAR constexpr bool is_pipeable_v<T &&> = META_IS_BASE_OF(pipeable_base,
  30. T);
  31. template<typename T>
  32. using is_pipeable = meta::bool_<is_pipeable_v<T>>;
  33. struct pipeable_access
  34. {
  35. template<typename Pipeable>
  36. struct impl : Pipeable
  37. {
  38. using Pipeable::pipe;
  39. };
  40. };
  41. struct pipeable_base
  42. {
  43. private:
  44. friend pipeable_access;
  45. template<typename Pipe0, typename Pipe1>
  46. struct composed;
  47. // Evaluate the pipe with an argument
  48. CPP_template(typename Arg, typename Pipe)( //
  49. requires(!is_pipeable_v<Arg>) && is_pipeable_v<Pipe>) // clang-format off
  50. constexpr friend auto operator|(Arg &&arg, Pipe pipe) // clang-format off
  51. {
  52. return pipeable_access::impl<Pipe>::pipe(static_cast<Arg &&>(arg), pipe);
  53. }
  54. // Compose two pipes
  55. CPP_template(typename Pipe0, typename Pipe1)( //
  56. requires is_pipeable_v<Pipe0> && is_pipeable_v<Pipe1>) // clang-format off
  57. constexpr friend auto operator|(Pipe0 pipe0, Pipe1 pipe1) // clang-format on
  58. {
  59. return composed<Pipe0, Pipe1>{pipe0, pipe1};
  60. }
  61. // Default Pipe behavior just passes the argument to the pipe's function call
  62. // operator
  63. // clang-format off
  64. template<typename Arg, typename Pipe>
  65. constexpr static auto CPP_auto_fun(pipe)(Arg &&arg, Pipe p)
  66. (
  67. return static_cast<Pipe &&>(p)(static_cast<Arg &&>(arg))
  68. )
  69. // clang-format on
  70. };
  71. template<typename Pipe0, typename Pipe1>
  72. struct pipeable_base::composed : pipeable_base
  73. {
  74. Pipe0 pipe0_;
  75. Pipe1 pipe1_;
  76. constexpr composed(Pipe0 pipe0, Pipe1 pipe1)
  77. : pipe0_(static_cast<Pipe0 &&>(pipe0))
  78. , pipe1_(static_cast<Pipe1 &&>(pipe1))
  79. {}
  80. // clang-format off
  81. template<typename Arg>
  82. constexpr auto CPP_auto_fun(operator())(Arg &&arg) (const)
  83. (
  84. return static_cast<Arg &&>(arg) | pipe0_ | pipe1_
  85. )
  86. // clang-format on
  87. };
  88. struct make_pipeable_fn
  89. {
  90. template<typename Fun>
  91. constexpr auto operator()(Fun fun) const
  92. {
  93. struct _
  94. : Fun
  95. , pipeable_base
  96. {
  97. constexpr explicit _(Fun && f)
  98. : Fun(static_cast<Fun &&>(f))
  99. {}
  100. };
  101. return _{static_cast<Fun &&>(fun)};
  102. }
  103. };
  104. /// \ingroup group-functional
  105. /// \sa `make_pipeable_fn`
  106. RANGES_INLINE_VARIABLE(make_pipeable_fn, make_pipeable)
  107. template<typename>
  108. using pipeable RANGES_DEPRECATED("Please use pipeable_base instead") = pipeable_base;
  109. /// \endcond
  110. /// @}
  111. } // namespace ranges
  112. #endif