#pragma once #include #include #include #include #include // Section: Non-Dependant Typedef Helpers namespace iterator::detail { template using category_t = typename std::iterator_traits::iterator_category; template using iter = decltype(std::begin(std::declval())); } namespace iterator::detail { // Type Helper for identifying container-like objects template struct is_container : std::false_type {}; template struct is_container>> : std::true_type {}; template struct sentinel_type { using type = void; }; template struct sentinel_type> { using type = typename It::sentinel_type; }; } // Mappings between iterator::category enum and iterator_category tags namespace iterator::detail { template (~0)> struct category_for { constexpr static category value = category::single_pass; }; template struct category_for { constexpr static category value = std::min(category::forward, Limit); }; template struct category_for { constexpr static category value = std::min(category::bidirectional, Limit); }; template struct category_for { constexpr static category value = std::min(category::random_access, Limit); }; template struct tag_for; template <> struct tag_for { using type = std::input_iterator_tag; }; template struct tag_for; template <> struct tag_for { using type = std::forward_iterator_tag; }; template struct tag_for; template <> struct tag_for { using type = std::bidirectional_iterator_tag; }; template struct tag_for; template <> struct tag_for { using type = std::random_access_iterator_tag; }; } namespace iterator::detail { template constexpr bool is_container_v = is_container{}; template constexpr bool is_rvalue_iterator_v = !std::is_reference_v; template constexpr bool has_sentinel_type_v = !std::is_void_v::type>; template constexpr bool is_sentinel_v = std::is_same_v::type, S>; template (~0)> constexpr auto category_for_v = category_for, Limit>::value; template using tag_for_t = typename tag_for::type; } #include