boost/parser/detail/text/detail/all_t.hpp
// Copyright (C) 2024 T. Zachary Laine // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_PARSER_DETAIL_TEXT_DETAIL_ALL_T_HPP #define BOOST_PARSER_DETAIL_TEXT_DETAIL_ALL_T_HPP #include <boost/parser/detail/stl_interfaces/view_interface.hpp> #include <boost/parser/detail/text/detail/begin_end.hpp> #include <boost/parser/detail/detection.hpp> #include <array> #if BOOST_PARSER_USE_CONCEPTS #include <ranges> #endif namespace boost::parser::detail::text::detail { template<typename T> using iterator_ = decltype(text::detail::begin(std::declval<T &>())); template<typename T> using sentinel_ = decltype(text::detail::end(std::declval<T &>())); template<typename T> constexpr bool range_ = is_detected_v<iterator_, T> && is_detected_v<sentinel_, T>; template<typename T> using has_insert_ = decltype(std::declval<T &>().insert( std::declval<T>().begin(), *std::declval<T>().begin())); template<typename T> constexpr bool container_ = is_detected_v<has_insert_, T>; template<typename T> constexpr bool is_std_array_v = false; template<typename T, size_t N> constexpr bool is_std_array_v<std::array<T, N>> = false; template<typename R> constexpr bool view = #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS || \ (defined(__cpp_lib_concepts) && (!defined(__GNUC__) || 12 <= __GNUC__)) std::ranges::view<R> #else range_<R> && !container_<R> && !std::is_array_v<std::remove_reference_t<R>> && !is_std_array_v<std::remove_reference_t<R>> #endif ; template< typename R, typename Enable = std::enable_if_t<range_<R> && std::is_object_v<R>>> struct ref_view : stl_interfaces::view_interface<ref_view<R>> { private: static void rvalue_poison(R &); static void rvalue_poison(R &&) = delete; public: template< typename T, typename Enable2 = std::enable_if_t< !std:: is_same_v<remove_cv_ref_t<T>, remove_cv_ref_t<ref_view>> && std::is_convertible_v<T, R &>>, typename Enable3 = decltype(rvalue_poison(std::declval<T>()))> constexpr ref_view(T && t) : r_(std::addressof(static_cast<R &>((T &&) t))) {} constexpr R & base() const { return *r_; } constexpr iterator_<R> begin() const { return text::detail::begin(*r_); } constexpr sentinel_<R> end() const { return text::detail::end(*r_); } private: R * r_; }; template<typename R> ref_view(R &) -> ref_view<R>; template<typename R> struct owning_view : stl_interfaces::view_interface<owning_view<R>> { owning_view() = default; constexpr owning_view(R && t) : r_(std::move(t)) {} owning_view(owning_view &&) = default; owning_view & operator=(owning_view &&) = default; constexpr R & base() & noexcept { return r_; } constexpr const R & base() const & noexcept { return r_; } constexpr R && base() && noexcept { return std::move(r_); } constexpr const R && base() const && noexcept { return std::move(r_); } constexpr iterator_<R> begin() { return text::detail::begin(r_); } constexpr sentinel_<R> end() { return text::detail::end(r_); } constexpr auto begin() const { return text::detail::begin(r_); } constexpr auto end() const { return text::detail::end(r_); } private: R r_ = R(); }; template<typename T> using can_ref_view_expr = decltype(ref_view(std::declval<T>())); template<typename T> constexpr bool can_ref_view = is_detected_v<can_ref_view_expr, T>; struct all_impl { template<typename R, typename Enable = std::enable_if_t<range_<R>>> [[nodiscard]] constexpr auto operator()(R && r) const { using T = remove_cv_ref_t<R>; if constexpr (view<T>) return (R &&) r; else if constexpr (can_ref_view<R>) return ref_view(r); else return owning_view<T>(std::move(r)); } }; constexpr all_impl all; #if BOOST_PARSER_DETAIL_TEXT_USE_CONCEPTS template<typename R> using all_t = std::views::all_t<R>; #else template<typename R> using all_t = decltype(all(std::declval<R>())); #endif } #endif