|
|
@@ -22,10 +22,13 @@ template <typename C>
|
|
|
struct is_container<C, std::void_t<iter<C>>> : std::true_type {};
|
|
|
|
|
|
template <typename It, typename = void>
|
|
|
-struct has_sentinel_type : std::false_type {};
|
|
|
+struct sentinel_type {
|
|
|
+ using type = void;
|
|
|
+};
|
|
|
template <typename It>
|
|
|
-struct has_sentinel_type<It, std::void_t<typename It::sentinel_type>>
|
|
|
- : std::true_type {};
|
|
|
+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
|
|
|
@@ -78,10 +81,10 @@ 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 = has_sentinel_type<It>{};
|
|
|
+constexpr bool has_sentinel_type_v = !std::is_void_v<typename sentinel_type<It>::type>;
|
|
|
|
|
|
template <typename It, typename S>
|
|
|
-using sentinel_type = std::conditional_t<std::is_same_v<It, S>, sentinel_t, 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;
|