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.

100 lines
3.7KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Johel Guerrero 2019
  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_ENDS_WITH_HPP
  14. #define RANGES_V3_ALGORITHM_ENDS_WITH_HPP
  15. #include <utility>
  16. #include <concepts/concepts.hpp>
  17. #include <range/v3/algorithm/equal.hpp>
  18. #include <range/v3/detail/config.hpp>
  19. #include <range/v3/functional/comparisons.hpp>
  20. #include <range/v3/functional/identity.hpp>
  21. #include <range/v3/iterator/concepts.hpp>
  22. #include <range/v3/iterator/operations.hpp>
  23. #include <range/v3/range/access.hpp>
  24. #include <range/v3/range/concepts.hpp>
  25. namespace ranges
  26. {
  27. /// \addtogroup group-algorithms
  28. /// @{
  29. RANGES_BEGIN_NIEBLOID(ends_with)
  30. /// \brief function template \c ends_with
  31. template<typename I0,
  32. typename S0,
  33. typename I1,
  34. typename S1,
  35. typename C = equal_to,
  36. typename P0 = identity,
  37. typename P1 = identity>
  38. constexpr auto RANGES_FUN_NIEBLOID(ends_with)(I0 begin0,
  39. S0 end0,
  40. I1 begin1,
  41. S1 end1,
  42. C pred = C{},
  43. P0 proj0 = P0{},
  44. P1 proj1 = P1{}) //
  45. ->CPP_ret(bool)( //
  46. requires((forward_iterator<I0> && sentinel_for<S0, I0>) ||
  47. (input_iterator<I0> && sized_sentinel_for<S0, I0>)) &&
  48. ((forward_iterator<I1> && sentinel_for<S1, I1>) ||
  49. (input_iterator<I1> && sized_sentinel_for<S1, I1>)) &&
  50. indirectly_comparable<I0, I1, C, P0, P1>)
  51. {
  52. const auto drop = distance(begin0, end0) - distance(begin1, end1);
  53. if(drop < 0)
  54. return false;
  55. return equal(next(std::move(begin0), drop),
  56. std::move(end0),
  57. std::move(begin1),
  58. std::move(end1),
  59. std::move(pred),
  60. std::move(proj0),
  61. std::move(proj1));
  62. }
  63. /// \overload
  64. template<typename Rng0,
  65. typename Rng1,
  66. typename C = equal_to,
  67. typename P0 = identity,
  68. typename P1 = identity>
  69. constexpr auto RANGES_FUN_NIEBLOID(ends_with)(
  70. Rng0 && rng0, Rng1 && rng1, C pred = C{}, P0 proj0 = P0{}, P1 proj1 = P1{}) //
  71. ->CPP_ret(bool)( //
  72. requires(forward_range<Rng0> ||
  73. (input_range<Rng0> && sized_range<Rng0>)) &&
  74. (forward_range<Rng1> || (input_range<Rng1> && sized_range<Rng1>)) &&
  75. indirectly_comparable<iterator_t<Rng0>, iterator_t<Rng1>, C, P0, P1>)
  76. {
  77. const auto drop = distance(rng0) - distance(rng1);
  78. if(drop < 0)
  79. return false;
  80. return equal(next(begin(rng0), drop),
  81. end(rng0),
  82. begin(rng1),
  83. end(rng1),
  84. std::move(pred),
  85. std::move(proj0),
  86. std::move(proj1));
  87. }
  88. RANGES_END_NIEBLOID(ends_with)
  89. /// @}
  90. } // namespace ranges
  91. #endif // include guard