#pragma once #include #include namespace iterator { struct sentinel_t; } namespace iterator::detail { template using iter = decltype(std::begin(std::declval())); // Type Helper for deducing reference types template struct reference_helper { using type = decltype(*std::declval()); }; template struct reference_helper> { using type = typename T::reference; }; // Type Helper for deducing value types template struct value_type_helper { using reference = typename reference_helper::type; using type = std::remove_cv_t>; }; template struct value_type_helper> { using type = typename T::value_type; }; // Type Helper for identifying container-like objects template struct is_container : std::false_type {}; template struct is_container>> : std::true_type {}; template struct has_sentinel_type : std::false_type {}; template struct has_sentinel_type> : std::true_type {}; template using value_type = typename value_type_helper::type; template using reference = typename reference_helper::type; template constexpr bool is_container_v = is_container{}; template constexpr bool is_rvalue_iterator_v = !std::is_reference_v>; template using category = typename std::iterator_traits::iterator_category; template constexpr bool is_random_access_v = std::is_same_v, std::random_access_iterator_tag>; template constexpr bool is_bidirectional_v = std::is_same_v, std::bidirectional_iterator_tag> || is_random_access_v; template constexpr bool is_forward_v = std::is_same_v, std::forward_iterator_tag> || is_bidirectional_v; template constexpr bool is_single_pass_v = !is_forward_v; template constexpr bool has_sentinel_type_v = has_sentinel_type{}; template using sentinel_type = std::conditional_t, sentinel_t, S>; }