all_t.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. // Copyright (C) 2024 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_DETAIL_TEXT_DETAIL_ALL_T_HPP
  7. #define BOOST_PARSER_DETAIL_TEXT_DETAIL_ALL_T_HPP
  8. #include <boost/parser/detail/stl_interfaces/view_interface.hpp>
  9. #include <boost/parser/detail/text/detail/begin_end.hpp>
  10. #include <boost/parser/detail/detection.hpp>
  11. #include <array>
  12. #if BOOST_PARSER_USE_CONCEPTS
  13. #include <ranges>
  14. #endif
  15. namespace boost::parser::detail::text::detail {
  16. template<typename T>
  17. using iterator_ = decltype(text::detail::begin(std::declval<T &>()));
  18. template<typename T>
  19. using sentinel_ = decltype(text::detail::end(std::declval<T &>()));
  20. template<typename T>
  21. constexpr bool range_ =
  22. is_detected_v<iterator_, T> && is_detected_v<sentinel_, T>;
  23. template<typename T>
  24. using has_insert_ = decltype(std::declval<T &>().insert(
  25. std::declval<T>().begin(), *std::declval<T>().begin()));
  26. template<typename T>
  27. constexpr bool container_ = is_detected_v<has_insert_, T>;
  28. template<typename T>
  29. constexpr bool is_std_array_v = false;
  30. template<typename T, size_t N>
  31. constexpr bool is_std_array_v<std::array<T, N>> = false;
  32. template<typename R>
  33. constexpr bool view =
  34. #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS || \
  35. (defined(__cpp_lib_concepts) && \
  36. (!defined(BOOST_PARSER_GCC) || 12 <= __GNUC__))
  37. std::ranges::view<R>
  38. #else
  39. range_<R> && !container_<R> &&
  40. !std::is_array_v<std::remove_reference_t<R>> &&
  41. !is_std_array_v<std::remove_reference_t<R>>
  42. #endif
  43. ;
  44. template<
  45. typename R,
  46. typename Enable = std::enable_if_t<range_<R> && std::is_object_v<R>>>
  47. struct ref_view : stl_interfaces::view_interface<ref_view<R>>
  48. {
  49. private:
  50. static void rvalue_poison(R &);
  51. static void rvalue_poison(R &&) = delete;
  52. public:
  53. template<
  54. typename T,
  55. typename Enable2 = std::enable_if_t<
  56. !std::
  57. is_same_v<remove_cv_ref_t<T>, remove_cv_ref_t<ref_view>> &&
  58. std::is_convertible_v<T, R &>>,
  59. typename Enable3 = decltype(rvalue_poison(std::declval<T>()))>
  60. constexpr ref_view(T && t) :
  61. r_(std::addressof(static_cast<R &>((T &&) t)))
  62. {}
  63. constexpr R & base() const { return *r_; }
  64. constexpr iterator_<R> begin() const
  65. {
  66. return text::detail::begin(*r_);
  67. }
  68. constexpr sentinel_<R> end() const { return text::detail::end(*r_); }
  69. private:
  70. R * r_;
  71. };
  72. template<typename R>
  73. ref_view(R &) -> ref_view<R>;
  74. template<typename R>
  75. struct owning_view : stl_interfaces::view_interface<owning_view<R>>
  76. {
  77. owning_view() = default;
  78. constexpr owning_view(R && t) : r_(std::move(t)) {}
  79. owning_view(owning_view &&) = default;
  80. owning_view & operator=(owning_view &&) = default;
  81. constexpr R & base() & noexcept { return r_; }
  82. constexpr const R & base() const & noexcept { return r_; }
  83. constexpr R && base() && noexcept { return std::move(r_); }
  84. constexpr const R && base() const && noexcept { return std::move(r_); }
  85. constexpr iterator_<R> begin() { return text::detail::begin(r_); }
  86. constexpr sentinel_<R> end() { return text::detail::end(r_); }
  87. constexpr auto begin() const { return text::detail::begin(r_); }
  88. constexpr auto end() const { return text::detail::end(r_); }
  89. private:
  90. R r_ = R();
  91. };
  92. template<typename T>
  93. using can_ref_view_expr = decltype(ref_view(std::declval<T>()));
  94. template<typename T>
  95. constexpr bool can_ref_view = is_detected_v<can_ref_view_expr, T>;
  96. struct all_impl
  97. {
  98. template<typename R, typename Enable = std::enable_if_t<range_<R>>>
  99. [[nodiscard]] constexpr auto operator()(R && r) const
  100. {
  101. using T = remove_cv_ref_t<R>;
  102. if constexpr (view<T>)
  103. return (R &&) r;
  104. else if constexpr (can_ref_view<R>)
  105. return ref_view(r);
  106. else
  107. return owning_view<T>((R &&)r);
  108. }
  109. };
  110. constexpr all_impl all;
  111. #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS
  112. template<typename R>
  113. using all_t = std::views::all_t<R>;
  114. #else
  115. template<typename R>
  116. using all_t = decltype(all(std::declval<R>()));
  117. #endif
  118. }
  119. #endif