|
|
@@ -19,9 +19,14 @@ struct is_tuple<std::array<T, N>> : std::true_type {};
|
|
|
template <typename... Ts>
|
|
|
struct is_tuple<std::tuple<Ts...>> : std::true_type {};
|
|
|
|
|
|
+template <typename, typename = void> struct is_wrapper : std::false_type {};
|
|
|
+template <typename T>
|
|
|
+struct is_wrapper<T, std::void_t<typename T::value_type>> : std::true_type {};
|
|
|
+
|
|
|
template <typename, typename = void> struct is_container : std::false_type {};
|
|
|
template <typename T>
|
|
|
-struct is_container<T, std::void_t<typename T::value_type>> : std::true_type {};
|
|
|
+struct is_container<T, std::void_t<decltype(std::begin(std::declval<T>()))>>
|
|
|
+ : is_wrapper<T> {};
|
|
|
|
|
|
template <typename, typename = void>
|
|
|
struct is_associative_container : std::false_type {};
|
|
|
@@ -38,14 +43,17 @@ struct has_serial_type<T, std::void_t<typename T::serial_type>>
|
|
|
template <typename, typename = void>
|
|
|
struct is_dereferencable : std::false_type {};
|
|
|
template <typename T>
|
|
|
-struct is_dereferencable<T, std::enable_if_t<!std::is_void_v<decltype(*T())>>> : std::true_type {};
|
|
|
+struct is_dereferencable<T, std::enable_if_t<!std::is_void_v<decltype(*T())>>>
|
|
|
+ : std::true_type {};
|
|
|
|
|
|
template <typename T> constexpr bool is_tuple_v = is_tuple<T>{};
|
|
|
+template <typename T> constexpr bool is_wrapper_v = is_wrapper<T>{};
|
|
|
template <typename T> constexpr bool is_container_v = is_container<T>{};
|
|
|
template <typename T>
|
|
|
constexpr bool is_associative_container_v =
|
|
|
is_container_v<T> && is_associative_container<T>{};
|
|
|
|
|
|
template <typename T> constexpr bool has_serial_type_v = has_serial_type<T>{};
|
|
|
-template <typename T> constexpr bool is_dereferencable_v = is_dereferencable<T>{};
|
|
|
+template <typename T>
|
|
|
+constexpr bool is_dereferencable_v = is_dereferencable<T>{};
|
|
|
}
|