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(BOOST_PARSER_GCC) || 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