boost/parser/subrange.hpp
// Copyright (C) 2022 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_SUBRANGE_HPP #define BOOST_PARSER_SUBRANGE_HPP #include <boost/parser/detail/text/config.hpp> #include <boost/parser/detail/text/detail/algorithm.hpp> #include <boost/parser/detail/stl_interfaces/view_interface.hpp> namespace boost::parser { /** A simple view type used throughout the rest of the library in C++17 builds; similar to `std::ranges::subrange`. */ #if BOOST_PARSER_USE_CONCEPTS template<std::forward_iterator I, std::sentinel_for<I> S = I> #else template<typename I, typename S = I> #endif struct subrange : detail::stl_interfaces::view_interface<subrange<I, S>> { constexpr subrange() = default; constexpr subrange(I first, S last) : first_(first), last_(last) {} template<typename R> constexpr explicit subrange(R const & r) : first_(detail::text::detail::begin(r)), last_(detail::text::detail::end(r)) {} constexpr I begin() const { return first_; } constexpr S end() const { return last_; } [[nodiscard]] constexpr subrange next(std::ptrdiff_t n = 1) const { return subrange{detail::text::detail::next(first_), last_}; } [[nodiscard]] constexpr subrange prev(std::ptrdiff_t n = 1) const { return subrange{detail::text::detail::prev(first_), last_}; } constexpr subrange & advance(std::ptrdiff_t n) { std::advance(first_, n); return *this; } template< typename I2, typename S2, typename Enable = std::enable_if_t< std::is_convertible<I, I2>::value && std::is_convertible<S, S2>::value>> constexpr operator subrange<I2, S2>() const { return {first_, last_}; } private: I first_; [[no_unique_address]] S last_; }; #if defined(__cpp_deduction_guides) #if BOOST_PARSER_USE_CONCEPTS template<std::input_or_output_iterator I, std::sentinel_for<I> S> #else template<typename I, typename S> #endif subrange(I, S) -> subrange<I, S>; #if BOOST_PARSER_USE_CONCEPTS template<std::ranges::borrowed_range R> #else template<typename R> #endif subrange(R &&) -> subrange< detail::text::detail::iterator_t<R>, detail::text::detail::sentinel_t<R>>; #endif /** Makes a `subrange<I, S>` from an `I` and an `S`. */ #if BOOST_PARSER_USE_CONCEPTS template<std::forward_iterator I, std::sentinel_for<I> S = I> #else template<typename I, typename S = I> #endif constexpr subrange<I, S> make_subrange(I first, S last) noexcept { return subrange<I, S>(first, last); } } #if BOOST_PARSER_USE_CONCEPTS namespace std::ranges { template<std::forward_iterator I, std::sentinel_for<I> S> inline constexpr bool enable_borrowed_range<boost::parser::subrange<I, S>> = true; } #endif #endif