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