Add type traits to check if a type is usable as object key
Add type trait to check:
* if a type is a specialization of a template.
* if a type is a json_pointer.
* if a type is a basic_json::{const_,}iterator.
* if two types are comparable using a given comparison functor.
* if a type is comparable to basic_json::object_t::key_type.
* if a type has a member type is_transparent.
* if a type is usable as object key.
* if a type has an erase() function accepting a given KeyType.
Co-authored-by: Niels Lohmann <niels.lohmann@gmail.com>
This commit is contained in:
parent
6df2a1a2cd
commit
0d790397a2
@ -54,11 +54,6 @@ struct is_basic_json_context :
|
||||
|| std::is_same<BasicJsonContext, std::nullptr_t>::value >
|
||||
{};
|
||||
|
||||
template<typename> struct is_json_pointer : std::false_type {};
|
||||
|
||||
template<typename RefStringType>
|
||||
struct is_json_pointer<json_pointer<RefStringType>> : std::true_type {};
|
||||
|
||||
//////////////////////
|
||||
// json_ref helpers //
|
||||
//////////////////////
|
||||
@ -472,6 +467,78 @@ struct is_constructible_tuple : std::false_type {};
|
||||
template<typename T1, typename... Args>
|
||||
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
|
||||
|
||||
template<typename BasicJsonType, typename T>
|
||||
struct is_json_iterator_of : std::false_type {};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
|
||||
{};
|
||||
|
||||
// checks if a given type T is a template specialization of Primary
|
||||
template<template <typename...> class Primary, typename T>
|
||||
struct is_specialization_of : std::false_type {};
|
||||
|
||||
template<template <typename...> class Primary, typename... Args>
|
||||
struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
|
||||
|
||||
template<typename T>
|
||||
using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
|
||||
|
||||
// checks if A and B are comparable using Compare functor
|
||||
template<typename Compare, typename A, typename B, typename = void>
|
||||
struct is_comparable : std::false_type {};
|
||||
|
||||
template<typename Compare, typename A, typename B>
|
||||
struct is_comparable<Compare, A, B, void_t<
|
||||
decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
|
||||
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
|
||||
>> : std::true_type {};
|
||||
|
||||
// checks if BasicJsonType::object_t::key_type and KeyType are comparable using Compare functor
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using is_key_type_comparable = typename is_comparable <
|
||||
typename BasicJsonType::object_comparator_t,
|
||||
const key_type_t<typename BasicJsonType::object_t>&,
|
||||
KeyType >::type;
|
||||
|
||||
template<typename T>
|
||||
using detect_is_transparent = typename T::is_transparent;
|
||||
|
||||
// type trait to check if KeyType can be used as object key
|
||||
// true if:
|
||||
// - KeyType is comparable with BasicJsonType::object_t::key_type
|
||||
// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
|
||||
// - the comparator is transparent or RequireTransparentComparator is false
|
||||
// - KeyType is not a JSON iterator or json_pointer
|
||||
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||
using is_usable_as_key_type = typename std::conditional <
|
||||
is_key_type_comparable<BasicJsonType, KeyTypeCVRef>::value
|
||||
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
|
||||
typename BasicJsonType::object_t::key_type>::value)
|
||||
&& (!RequireTransparentComparator || is_detected <
|
||||
detect_is_transparent,
|
||||
typename BasicJsonType::object_comparator_t >::value)
|
||||
&& !is_json_iterator_of<BasicJsonType, KeyType>::value
|
||||
&& !is_json_pointer<KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
template<typename ObjectType, typename KeyType>
|
||||
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
|
||||
|
||||
// type trait to check if object_t has an erase() member functions accepting KeyType
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using has_erase_with_key_type = typename std::conditional <
|
||||
is_detected <
|
||||
detect_erase_with_key_type,
|
||||
typename BasicJsonType::object_t, KeyType >::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
// a naive helper to check if a type is an ordered_map (exploits the fact that
|
||||
// ordered_map inherits capacity() from std::vector)
|
||||
template <typename T>
|
||||
|
||||
@ -3189,11 +3189,6 @@ struct is_basic_json_context :
|
||||
|| std::is_same<BasicJsonContext, std::nullptr_t>::value >
|
||||
{};
|
||||
|
||||
template<typename> struct is_json_pointer : std::false_type {};
|
||||
|
||||
template<typename RefStringType>
|
||||
struct is_json_pointer<json_pointer<RefStringType>> : std::true_type {};
|
||||
|
||||
//////////////////////
|
||||
// json_ref helpers //
|
||||
//////////////////////
|
||||
@ -3607,6 +3602,78 @@ struct is_constructible_tuple : std::false_type {};
|
||||
template<typename T1, typename... Args>
|
||||
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
|
||||
|
||||
template<typename BasicJsonType, typename T>
|
||||
struct is_json_iterator_of : std::false_type {};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
|
||||
{};
|
||||
|
||||
// checks if a given type T is a template specialization of Primary
|
||||
template<template <typename...> class Primary, typename T>
|
||||
struct is_specialization_of : std::false_type {};
|
||||
|
||||
template<template <typename...> class Primary, typename... Args>
|
||||
struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
|
||||
|
||||
template<typename T>
|
||||
using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
|
||||
|
||||
// checks if A and B are comparable using Compare functor
|
||||
template<typename Compare, typename A, typename B, typename = void>
|
||||
struct is_comparable : std::false_type {};
|
||||
|
||||
template<typename Compare, typename A, typename B>
|
||||
struct is_comparable<Compare, A, B, void_t<
|
||||
decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
|
||||
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
|
||||
>> : std::true_type {};
|
||||
|
||||
// checks if BasicJsonType::object_t::key_type and KeyType are comparable using Compare functor
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using is_key_type_comparable = typename is_comparable <
|
||||
typename BasicJsonType::object_comparator_t,
|
||||
const key_type_t<typename BasicJsonType::object_t>&,
|
||||
KeyType >::type;
|
||||
|
||||
template<typename T>
|
||||
using detect_is_transparent = typename T::is_transparent;
|
||||
|
||||
// type trait to check if KeyType can be used as object key
|
||||
// true if:
|
||||
// - KeyType is comparable with BasicJsonType::object_t::key_type
|
||||
// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
|
||||
// - the comparator is transparent or RequireTransparentComparator is false
|
||||
// - KeyType is not a JSON iterator or json_pointer
|
||||
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||
using is_usable_as_key_type = typename std::conditional <
|
||||
is_key_type_comparable<BasicJsonType, KeyTypeCVRef>::value
|
||||
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
|
||||
typename BasicJsonType::object_t::key_type>::value)
|
||||
&& (!RequireTransparentComparator || is_detected <
|
||||
detect_is_transparent,
|
||||
typename BasicJsonType::object_comparator_t >::value)
|
||||
&& !is_json_iterator_of<BasicJsonType, KeyType>::value
|
||||
&& !is_json_pointer<KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
template<typename ObjectType, typename KeyType>
|
||||
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
|
||||
|
||||
// type trait to check if object_t has an erase() member functions accepting KeyType
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using has_erase_with_key_type = typename std::conditional <
|
||||
is_detected <
|
||||
detect_erase_with_key_type,
|
||||
typename BasicJsonType::object_t, KeyType >::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
// a naive helper to check if a type is an ordered_map (exploits the fact that
|
||||
// ordered_map inherits capacity() from std::vector)
|
||||
template <typename T>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user