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.

176 lines
6.9KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2014-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 0.0. (See accompanying
  8. // file LICENSE_0_0.txt or copy at
  9. // http://www.boost.org/LICENSE_0_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_ALGORITHM_EQUAL_HPP
  14. #define RANGES_V3_ALGORITHM_EQUAL_HPP
  15. #include <utility>
  16. #include <range/v3/range_fwd.hpp>
  17. #include <range/v3/functional/comparisons.hpp>
  18. #include <range/v3/functional/identity.hpp>
  19. #include <range/v3/functional/invoke.hpp>
  20. #include <range/v3/iterator/concepts.hpp>
  21. #include <range/v3/iterator/operations.hpp>
  22. #include <range/v3/iterator/traits.hpp>
  23. #include <range/v3/range/access.hpp>
  24. #include <range/v3/range/concepts.hpp>
  25. #include <range/v3/range/traits.hpp>
  26. #include <range/v3/utility/static_const.hpp>
  27. namespace ranges
  28. {
  29. /// \addtogroup group-algorithms
  30. /// @{
  31. /// \cond
  32. namespace detail
  33. {
  34. template<typename I0, typename S0, typename I1, typename S1, typename C,
  35. typename P0, typename P1>
  36. constexpr bool equal_nocheck(I0 begin0, S0 end0, I1 begin1, S1 end1, C pred,
  37. P0 proj0, P1 proj1)
  38. {
  39. for(; begin0 != end0 && begin1 != end1; ++begin0, ++begin1)
  40. if(!invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1)))
  41. return false;
  42. return begin0 == end0 && begin1 == end1;
  43. }
  44. } // namespace detail
  45. /// \endcond
  46. RANGES_BEGIN_NIEBLOID(equal)
  47. /// \brief function template \c equal
  48. template<typename I0,
  49. typename S0,
  50. typename I1,
  51. typename C = equal_to,
  52. typename P0 = identity,
  53. typename P1 = identity>
  54. RANGES_DEPRECATED(
  55. "Use the variant of ranges::equal that takes an upper bound for "
  56. "both sequences")
  57. constexpr auto RANGES_FUN_NIEBLOID(equal)(I0 begin0,
  58. S0 end0,
  59. I1 begin1,
  60. C pred = C{},
  61. P0 proj0 = P0{},
  62. P1 proj1 = P1{}) //
  63. ->CPP_ret(bool)( //
  64. requires input_iterator<I0> && sentinel_for<S0, I0> &&
  65. input_iterator<I1> && indirectly_comparable<I0, I1, C, P0, P1>)
  66. {
  67. for(; begin0 != end0; ++begin0, ++begin1)
  68. if(!invoke(pred, invoke(proj0, *begin0), invoke(proj1, *begin1)))
  69. return false;
  70. return true;
  71. }
  72. /// \overload
  73. template<typename I0,
  74. typename S0,
  75. typename I1,
  76. typename S1,
  77. typename C = equal_to,
  78. typename P0 = identity,
  79. typename P1 = identity>
  80. constexpr auto RANGES_FUN_NIEBLOID(equal)(I0 begin0,
  81. S0 end0,
  82. I1 begin1,
  83. S1 end1,
  84. C pred = C{},
  85. P0 proj0 = P0{},
  86. P1 proj1 = P1{}) //
  87. ->CPP_ret(bool)( //
  88. requires input_iterator<I0> && sentinel_for<S0, I0> &&
  89. input_iterator<I1> && sentinel_for<S1, I1> &&
  90. indirectly_comparable<I0, I1, C, P0, P1>)
  91. {
  92. if(RANGES_CONSTEXPR_IF(sized_sentinel_for<S0, I0> &&
  93. sized_sentinel_for<S1, I1>))
  94. if(distance(begin0, end0) != distance(begin1, end1))
  95. return false;
  96. return detail::equal_nocheck(std::move(begin0),
  97. std::move(end0),
  98. std::move(begin1),
  99. std::move(end1),
  100. std::move(pred),
  101. std::move(proj0),
  102. std::move(proj1));
  103. }
  104. /// \overload
  105. template<typename Rng0,
  106. typename I1Ref,
  107. typename C = equal_to,
  108. typename P0 = identity,
  109. typename P1 = identity>
  110. RANGES_DEPRECATED(
  111. "Use the variant of ranges::equal that takes an upper bound for "
  112. "both sequences")
  113. constexpr auto RANGES_FUN_NIEBLOID(equal)(Rng0 && rng0,
  114. I1Ref && begin1,
  115. C pred = C{},
  116. P0 proj0 = P0{},
  117. P1 proj1 = P1{}) //
  118. ->CPP_ret(bool)( //
  119. requires input_range<Rng0> && input_iterator<uncvref_t<I1Ref>> &&
  120. indirectly_comparable<iterator_t<Rng0>, uncvref_t<I1Ref>, C, P0, P1>)
  121. {
  122. RANGES_DIAGNOSTIC_PUSH
  123. RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
  124. return (*this)(begin(rng0),
  125. end(rng0),
  126. (I1Ref &&) begin1,
  127. std::move(pred),
  128. std::move(proj0),
  129. std::move(proj1));
  130. RANGES_DIAGNOSTIC_POP
  131. }
  132. /// \overload
  133. template<typename Rng0,
  134. typename Rng1,
  135. typename C = equal_to,
  136. typename P0 = identity,
  137. typename P1 = identity>
  138. constexpr auto RANGES_FUN_NIEBLOID(equal)(
  139. Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = P1{}) //
  140. ->CPP_ret(bool)( //
  141. requires input_range<Rng0> && input_range<Rng1> &&
  142. indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>)
  143. {
  144. if(RANGES_CONSTEXPR_IF(sized_range<Rng0> && sized_range<Rng1>))
  145. if(distance(rng0) != distance(rng1))
  146. return false;
  147. return detail::equal_nocheck(begin(rng0),
  148. end(rng0),
  149. begin(rng1),
  150. end(rng1),
  151. std::move(pred),
  152. std::move(proj0),
  153. std::move(proj1));
  154. }
  155. RANGES_END_NIEBLOID(equal)
  156. namespace cpp20
  157. {
  158. using ranges::equal;
  159. }
  160. /// @}
  161. } // namespace ranges
  162. #endif // include guard