overload.hpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  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_OVERLOAD_HPP
  14. #define RANGES_V3_FUNCTIONAL_OVERLOAD_HPP
  15. #include <meta/meta.hpp>
  16. #include <concepts/concepts.hpp>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/functional/concepts.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. /// \cond
  27. namespace detail
  28. {
  29. struct _id
  30. {
  31. template<typename T>
  32. using invoke = T;
  33. };
  34. struct _ref
  35. {
  36. template<typename T>
  37. using invoke = T &;
  38. };
  39. struct _cref
  40. {
  41. template<typename T>
  42. using invoke = T const &;
  43. };
  44. template<typename T>
  45. struct _bind_front
  46. {
  47. template<typename... Args>
  48. using invoke = invoke_result_t<T, Args...>;
  49. };
  50. } // namespace detail
  51. /// \endcond
  52. template<typename... Ts>
  53. struct overloaded;
  54. template<>
  55. struct overloaded<>
  56. {
  57. private:
  58. template<typename...>
  59. friend struct overloaded;
  60. template<typename, typename...>
  61. using _result_t = void;
  62. };
  63. template<typename First, typename... Rest>
  64. struct overloaded<First, Rest...>
  65. {
  66. private:
  67. template<typename...>
  68. friend struct overloaded;
  69. RANGES_NO_UNIQUE_ADDRESS
  70. First first_;
  71. RANGES_NO_UNIQUE_ADDRESS
  72. overloaded<Rest...> second_;
  73. template<typename Qual>
  74. using _result_first = detail::_bind_front<meta::invoke<Qual, First>>;
  75. template<typename Qual>
  76. struct _result_second
  77. {
  78. template<typename... Args>
  79. using invoke = typename overloaded<Rest...>
  80. ::template _result_t<Qual, Args...>;
  81. };
  82. template<typename Qual, typename... Args>
  83. using _result_t =
  84. meta::invoke<
  85. meta::conditional_t<
  86. (bool) invocable<meta::invoke<Qual, First>, Args...>,
  87. _result_first<Qual>,
  88. _result_second<Qual>>,
  89. Args...>;
  90. public:
  91. overloaded() = default;
  92. constexpr overloaded(First first, Rest... rest)
  93. : first_(static_cast<First &&>(first))
  94. , second_{static_cast<Rest &&>(rest)...}
  95. {}
  96. template(typename... Args)(
  97. requires invocable<First, Args...>)
  98. constexpr _result_t<detail::_id, Args...> operator()(Args &&... args) &&
  99. {
  100. return invoke((First &&) first_, (Args &&) args...);
  101. }
  102. template(typename... Args)(
  103. requires (!invocable<First, Args...>) AND
  104. invocable<overloaded<Rest...>, Args...>)
  105. constexpr _result_t<detail::_id, Args...> operator()(Args &&... args) &&
  106. {
  107. return invoke((overloaded<Rest...> &&) second_, (Args &&) args...);
  108. }
  109. template(typename... Args)(
  110. requires invocable<First &, Args...>)
  111. constexpr _result_t<detail::_ref, Args...> operator()(Args &&... args) &
  112. {
  113. return invoke(first_, (Args &&) args...);
  114. }
  115. template(typename... Args)(
  116. requires (!invocable<First &, Args...>) AND
  117. invocable<overloaded<Rest...> &, Args...>)
  118. constexpr _result_t<detail::_ref, Args...> operator()(Args &&... args) &
  119. {
  120. return invoke(second_, (Args &&) args...);
  121. }
  122. template(typename... Args)(
  123. requires invocable<First const &, Args...>)
  124. constexpr _result_t<detail::_cref, Args...> operator()(Args &&... args) const &
  125. {
  126. return invoke(first_, (Args &&) args...);
  127. }
  128. template(typename... Args)(
  129. requires (!invocable<First const &, Args...>) AND
  130. invocable<overloaded<Rest...> const &, Args...>)
  131. constexpr _result_t<detail::_cref, Args...> operator()(Args &&... args) const &
  132. {
  133. return invoke(second_, (Args &&) args...);
  134. }
  135. };
  136. struct overload_fn
  137. {
  138. template<typename Fn>
  139. constexpr Fn operator()(Fn fn) const
  140. {
  141. return fn;
  142. }
  143. template<typename... Fns>
  144. constexpr overloaded<Fns...> operator()(Fns... fns) const
  145. {
  146. return overloaded<Fns...>{static_cast<Fns &&>(fns)...};
  147. }
  148. };
  149. /// \ingroup group-functional
  150. /// \sa `overload_fn`
  151. RANGES_INLINE_VARIABLE(overload_fn, overload)
  152. /// @}
  153. } // namespace ranges
  154. #include <range/v3/detail/epilogue.hpp>
  155. #endif