subrange.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. // Copyright (C) 2022 T. Zachary Laine
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See
  4. // accompanying file LICENSE_1_0.txt or copy at
  5. // http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_PARSER_SUBRANGE_HPP
  7. #define BOOST_PARSER_SUBRANGE_HPP
  8. #include <boost/parser/detail/text/config.hpp>
  9. #include <boost/parser/detail/text/detail/algorithm.hpp>
  10. #include <boost/parser/detail/stl_interfaces/view_interface.hpp>
  11. namespace boost::parser {
  12. /** A simple view type used throughout the rest of the library in C++17
  13. builds; similar to `std::ranges::subrange`. */
  14. #if BOOST_PARSER_USE_CONCEPTS
  15. template<std::forward_iterator I, std::sentinel_for<I> S = I>
  16. #else
  17. template<typename I, typename S = I>
  18. #endif
  19. struct subrange : detail::stl_interfaces::view_interface<subrange<I, S>>
  20. {
  21. constexpr subrange() = default;
  22. constexpr subrange(I first, S last) : first_(first), last_(last) {}
  23. template<typename R>
  24. constexpr explicit subrange(R const & r) :
  25. first_(detail::text::detail::begin(r)),
  26. last_(detail::text::detail::end(r))
  27. {}
  28. constexpr I begin() const { return first_; }
  29. constexpr S end() const { return last_; }
  30. [[nodiscard]] constexpr subrange next(std::ptrdiff_t n = 1) const
  31. {
  32. return subrange{detail::text::detail::next(first_), last_};
  33. }
  34. [[nodiscard]] constexpr subrange prev(std::ptrdiff_t n = 1) const
  35. {
  36. return subrange{detail::text::detail::prev(first_), last_};
  37. }
  38. constexpr subrange & advance(std::ptrdiff_t n)
  39. {
  40. std::advance(first_, n);
  41. return *this;
  42. }
  43. template<
  44. typename I2,
  45. typename S2,
  46. typename Enable = std::enable_if_t<
  47. std::is_convertible<I, I2>::value &&
  48. std::is_convertible<S, S2>::value>>
  49. constexpr operator subrange<I2, S2>() const
  50. {
  51. return {first_, last_};
  52. }
  53. private:
  54. I first_;
  55. [[no_unique_address]] S last_;
  56. };
  57. #if defined(__cpp_deduction_guides)
  58. #if BOOST_PARSER_USE_CONCEPTS
  59. template<std::input_or_output_iterator I, std::sentinel_for<I> S>
  60. #else
  61. template<typename I, typename S>
  62. #endif
  63. subrange(I, S) -> subrange<I, S>;
  64. #if BOOST_PARSER_USE_CONCEPTS
  65. template<std::ranges::borrowed_range R>
  66. #else
  67. template<typename R>
  68. #endif
  69. subrange(R &&) -> subrange<
  70. detail::text::detail::iterator_t<R>,
  71. detail::text::detail::sentinel_t<R>>;
  72. #endif
  73. /** Makes a `subrange<I, S>` from an `I` and an `S`. */
  74. #if BOOST_PARSER_USE_CONCEPTS
  75. template<std::forward_iterator I, std::sentinel_for<I> S = I>
  76. #else
  77. template<typename I, typename S = I>
  78. #endif
  79. constexpr subrange<I, S> make_subrange(I first, S last) noexcept
  80. {
  81. return subrange<I, S>(first, last);
  82. }
  83. }
  84. #if BOOST_PARSER_USE_CONCEPTS
  85. namespace std::ranges {
  86. template<std::forward_iterator I, std::sentinel_for<I> S>
  87. inline constexpr bool enable_borrowed_range<boost::parser::subrange<I, S>> =
  88. true;
  89. }
  90. #endif
  91. #endif