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.

171 lines
6.5KB

  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 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_ALGORITHM_MISMATCH_HPP
  14. #define RANGES_V3_ALGORITHM_MISMATCH_HPP
  15. #include <utility>
  16. #include <meta/meta.hpp>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/algorithm/result_types.hpp>
  19. #include <range/v3/functional/comparisons.hpp>
  20. #include <range/v3/functional/identity.hpp>
  21. #include <range/v3/functional/invoke.hpp>
  22. #include <range/v3/iterator/concepts.hpp>
  23. #include <range/v3/iterator/traits.hpp>
  24. #include <range/v3/range/access.hpp>
  25. #include <range/v3/range/concepts.hpp>
  26. #include <range/v3/range/dangling.hpp>
  27. #include <range/v3/range/traits.hpp>
  28. #include <range/v3/utility/static_const.hpp>
  29. namespace ranges
  30. {
  31. /// \addtogroup group-algorithms
  32. /// @{
  33. template<typename I1, typename I2>
  34. using mismatch_result = detail::in1_in2_result<I1, I2>;
  35. RANGES_BEGIN_NIEBLOID(mismatch)
  36. /// \brief function template \c mismatch
  37. template<typename I1,
  38. typename S1,
  39. typename I2,
  40. typename C = equal_to,
  41. typename P1 = identity,
  42. typename P2 = identity>
  43. RANGES_DEPRECATED(
  44. "Use the variant of ranges::mismatch that takes an upper bound for "
  45. "both sequences")
  46. auto RANGES_FUN_NIEBLOID(mismatch)(I1 begin1,
  47. S1 end1,
  48. I2 begin2,
  49. C pred = C{},
  50. P1 proj1 = P1{},
  51. P2 proj2 = P2{}) //
  52. ->CPP_ret(mismatch_result<I1, I2>)( //
  53. requires input_iterator<I1> && sentinel_for<S1, I1> &&
  54. input_iterator<I2> &&
  55. indirect_relation<C, projected<I1, P1>, projected<I2, P2>>)
  56. {
  57. for(; begin1 != end1; ++begin1, ++begin2)
  58. if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
  59. break;
  60. return {begin1, begin2};
  61. }
  62. /// \overload
  63. template<typename I1,
  64. typename S1,
  65. typename I2,
  66. typename S2,
  67. typename C = equal_to,
  68. typename P1 = identity,
  69. typename P2 = identity>
  70. auto RANGES_FUN_NIEBLOID(mismatch)(I1 begin1,
  71. S1 end1,
  72. I2 begin2,
  73. S2 end2,
  74. C pred = C{},
  75. P1 proj1 = P1{},
  76. P2 proj2 = P2{}) //
  77. ->CPP_ret(mismatch_result<I1, I2>)( //
  78. requires input_iterator<I1> && sentinel_for<S1, I1> &&
  79. input_iterator<I2> && sentinel_for<S2, I2> &&
  80. indirect_relation<C, projected<I1, P1>, projected<I2, P2>>)
  81. {
  82. for(; begin1 != end1 && begin2 != end2; ++begin1, ++begin2)
  83. if(!invoke(pred, invoke(proj1, *begin1), invoke(proj2, *begin2)))
  84. break;
  85. return {begin1, begin2};
  86. }
  87. /// \overload
  88. template<typename Rng1,
  89. typename I2Ref,
  90. typename C = equal_to,
  91. typename P1 = identity,
  92. typename P2 = identity>
  93. RANGES_DEPRECATED(
  94. "Use the variant of ranges::mismatch that takes an upper bound for "
  95. "both sequences")
  96. auto RANGES_FUN_NIEBLOID(mismatch)(Rng1 && rng1,
  97. I2Ref && begin2,
  98. C pred = C{}, // see below [*]
  99. P1 proj1 = P1{},
  100. P2 proj2 = P2{}) //
  101. ->CPP_ret(mismatch_result<safe_iterator_t<Rng1>, uncvref_t<I2Ref>>)( //
  102. requires input_range<Rng1> && input_iterator<uncvref_t<I2Ref>> &&
  103. indirect_relation<C,
  104. projected<iterator_t<Rng1>, P1>,
  105. projected<uncvref_t<I2Ref>, P2>>)
  106. {
  107. RANGES_DIAGNOSTIC_PUSH
  108. RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
  109. return (*this)(begin(rng1),
  110. end(rng1),
  111. static_cast<uncvref_t<I2Ref> &&>(begin2),
  112. std::move(pred),
  113. std::move(proj1),
  114. std::move(proj2));
  115. RANGES_DIAGNOSTIC_POP
  116. }
  117. /// \overload
  118. template<typename Rng1,
  119. typename Rng2,
  120. typename C = equal_to,
  121. typename P1 = identity,
  122. typename P2 = identity>
  123. auto RANGES_FUN_NIEBLOID(mismatch)(
  124. Rng1 && rng1, Rng2 && rng2, C pred = C{}, P1 proj1 = P1{}, P2 proj2 = P2{}) //
  125. ->CPP_ret(mismatch_result<safe_iterator_t<Rng1>, safe_iterator_t<Rng2>>)( //
  126. requires input_range<Rng1> && input_range<Rng2> &&
  127. indirect_relation<C,
  128. projected<iterator_t<Rng1>, P1>,
  129. projected<iterator_t<Rng2>, P2>>)
  130. {
  131. return (*this)(begin(rng1),
  132. end(rng1),
  133. begin(rng2),
  134. end(rng2),
  135. std::move(pred),
  136. std::move(proj1),
  137. std::move(proj2));
  138. }
  139. RANGES_END_NIEBLOID(mismatch)
  140. namespace cpp20
  141. {
  142. using ranges::mismatch;
  143. using ranges::mismatch_result;
  144. } // namespace cpp20
  145. // [*] In this case, the 'begin2' iterator is taken by universal reference. Why? So
  146. // that we can properly distinguish this case:
  147. // int x[] = {1,2,3,4};
  148. // int y[] = {1,2,3,4};
  149. // mismatch(x, y);
  150. // Had 'begin2' been taken by value as is customary, this call could match as either
  151. // two ranges, or a range and an iterator, where the iterator is the array, decayed
  152. // to a pointer. Yuk!
  153. /// @}
  154. } // namespace ranges
  155. #endif // include guard