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.

97 lines
2.5KB

  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_INDIRECT_HPP
  14. #define RANGES_V3_FUNCTIONAL_INDIRECT_HPP
  15. #include <utility>
  16. #include <concepts/concepts.hpp>
  17. #include <range/v3/functional/invoke.hpp>
  18. #include <range/v3/iterator/traits.hpp>
  19. #include <range/v3/utility/move.hpp>
  20. #include <range/v3/utility/static_const.hpp>
  21. namespace ranges
  22. {
  23. /// \addtogroup group-functional
  24. /// @{
  25. template<typename Fn>
  26. struct indirected
  27. {
  28. private:
  29. RANGES_NO_UNIQUE_ADDRESS
  30. Fn fn_;
  31. public:
  32. indirected() = default;
  33. indirected(Fn fn)
  34. : fn_(std::move(fn))
  35. {}
  36. // value_type (needs no impl)
  37. template<typename... Its>
  38. [[noreturn]] auto operator()(copy_tag, Its...) const
  39. -> invoke_result_t<Fn &, iter_reference_t<Its>...>
  40. {
  41. RANGES_EXPECT(false);
  42. }
  43. // Reference
  44. // clang-format off
  45. template<typename... Its>
  46. auto CPP_auto_fun(operator())(Its... its)
  47. (
  48. return invoke(fn_, *its...)
  49. )
  50. template<typename... Its>
  51. auto CPP_auto_fun(operator())(Its... its)(const)
  52. (
  53. return invoke((Fn const &)fn_, *its...)
  54. )
  55. // Rvalue reference
  56. template<typename... Its>
  57. auto CPP_auto_fun(operator())(move_tag, Its... its)
  58. (
  59. return static_cast<
  60. aux::move_t<invoke_result_t<Fn &, iter_reference_t<Its>...>>>(
  61. aux::move(invoke(fn_, *its...)))
  62. )
  63. template<typename... Its>
  64. auto CPP_auto_fun(operator())(move_tag, Its... its)(const)
  65. (
  66. return static_cast<
  67. aux::move_t<invoke_result_t<Fn const &, iter_reference_t<Its>...>>>(
  68. aux::move(invoke((Fn const &)fn_, *its...)))
  69. )
  70. // clang-format on
  71. };
  72. struct indirect_fn
  73. {
  74. template<typename Fn>
  75. constexpr indirected<Fn> operator()(Fn fn) const
  76. {
  77. return indirected<Fn>{detail::move(fn)};
  78. }
  79. };
  80. /// \ingroup group-functional
  81. /// \sa `indirect_fn`
  82. RANGES_INLINE_VARIABLE(indirect_fn, indirect)
  83. /// @}
  84. } // namespace ranges
  85. #endif