use detected instead of has_* traits
This commit is contained in:
		
							parent
							
								
									1ea8cd128c
								
							
						
					
					
						commit
						b59c3367c9
					
				
					 4 changed files with 157 additions and 178 deletions
				
			
		| 
						 | 
				
			
			@ -218,25 +218,6 @@ using json = basic_json<>;
 | 
			
		|||
    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
 | 
			
		||||
    AllocatorType, JSONSerializer>
 | 
			
		||||
 | 
			
		||||
/*!
 | 
			
		||||
@brief Helper to determine whether there's a key_type for T.
 | 
			
		||||
 | 
			
		||||
This helper is used to tell associative containers apart from other containers
 | 
			
		||||
such as sequence containers. For instance, `std::map` passes the test as it
 | 
			
		||||
contains a `mapped_type`, whereas `std::vector` fails the test.
 | 
			
		||||
 | 
			
		||||
@sa http://stackoverflow.com/a/7728728/266378
 | 
			
		||||
@since version 1.0.0, overworked in version 2.0.6
 | 
			
		||||
*/
 | 
			
		||||
#define NLOHMANN_JSON_HAS_HELPER(type)                                        \
 | 
			
		||||
    template<typename T> struct has_##type {                                  \
 | 
			
		||||
        template<typename U, typename = typename U::type>                     \
 | 
			
		||||
        static int detect(U &&);                                              \
 | 
			
		||||
        static void detect(...);                                              \
 | 
			
		||||
        static constexpr bool value =                                         \
 | 
			
		||||
                std::is_integral<decltype(detect(std::declval<T>()))>::value; \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
// #include <nlohmann/detail/meta/cpp_future.hpp>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -334,6 +315,78 @@ constexpr T static_const<T>::value;
 | 
			
		|||
 | 
			
		||||
// #include <nlohmann/detail/meta/cpp_future.hpp>
 | 
			
		||||
 | 
			
		||||
// #include <nlohmann/detail/meta/detected.hpp>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
// #include <nlohmann/detail/meta/void_t.hpp>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace nlohmann
 | 
			
		||||
{
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
template <typename ...Ts> struct make_void
 | 
			
		||||
{
 | 
			
		||||
    using type = void;
 | 
			
		||||
};
 | 
			
		||||
template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// http://en.cppreference.com/w/cpp/experimental/is_detected
 | 
			
		||||
namespace nlohmann
 | 
			
		||||
{
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
struct nonesuch
 | 
			
		||||
{
 | 
			
		||||
    nonesuch() = delete;
 | 
			
		||||
    ~nonesuch() = delete;
 | 
			
		||||
    nonesuch(nonesuch const&) = delete;
 | 
			
		||||
    void operator=(nonesuch const&) = delete;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Default,
 | 
			
		||||
          class AlwaysVoid,
 | 
			
		||||
          template <class...> class Op,
 | 
			
		||||
          class... Args>
 | 
			
		||||
struct detector
 | 
			
		||||
{
 | 
			
		||||
    using value_t = std::false_type;
 | 
			
		||||
    using type = Default;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Default, template <class...> class Op, class... Args>
 | 
			
		||||
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
 | 
			
		||||
{
 | 
			
		||||
    using value_t = std::true_type;
 | 
			
		||||
    using type = Op<Args...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <template <class...> class Op, class... Args>
 | 
			
		||||
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
 | 
			
		||||
 | 
			
		||||
template <template <class...> class Op, class... Args>
 | 
			
		||||
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
 | 
			
		||||
 | 
			
		||||
template <class Default, template <class...> class Op, class... Args>
 | 
			
		||||
using detected_or = detector<Default, void, Op, Args...>;
 | 
			
		||||
 | 
			
		||||
template <class Default, template <class...> class Op, class... Args>
 | 
			
		||||
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
 | 
			
		||||
 | 
			
		||||
template <class Expected, template <class...> class Op, class... Args>
 | 
			
		||||
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
 | 
			
		||||
 | 
			
		||||
template <class To, template <class...> class Op, class... Args>
 | 
			
		||||
using is_detected_convertible =
 | 
			
		||||
    std::is_convertible<detected_t<Op, Args...>, To>;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// #include <nlohmann/detail/macro_scope.hpp>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -358,9 +411,31 @@ template<typename> struct is_basic_json : std::false_type {};
 | 
			
		|||
NLOHMANN_BASIC_JSON_TPL_DECLARATION
 | 
			
		||||
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
 | 
			
		||||
 | 
			
		||||
////////////////////////
 | 
			
		||||
// has_/is_ functions //
 | 
			
		||||
////////////////////////
 | 
			
		||||
//////////////////////////
 | 
			
		||||
// aliases for detected //
 | 
			
		||||
//////////////////////////
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using mapped_type_t = typename T::mapped_type;
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using key_type_t = typename T::key_type;
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using value_type_t = typename T::value_type;
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using iterator_t = typename T::iterator;
 | 
			
		||||
 | 
			
		||||
template <typename T, typename... Args>
 | 
			
		||||
using to_json_function = decltype(T::to_json(std::declval<Args>()...));
 | 
			
		||||
 | 
			
		||||
template <typename T, typename... Args>
 | 
			
		||||
using from_json_function = decltype(T::from_json(std::declval<Args>()...));
 | 
			
		||||
 | 
			
		||||
///////////////////
 | 
			
		||||
// is_ functions //
 | 
			
		||||
///////////////////
 | 
			
		||||
 | 
			
		||||
// source: https://stackoverflow.com/a/37193089/4116453
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -370,11 +445,6 @@ struct is_complete_type : std::false_type {};
 | 
			
		|||
template <typename T>
 | 
			
		||||
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
 | 
			
		||||
 | 
			
		||||
NLOHMANN_JSON_HAS_HELPER(mapped_type);
 | 
			
		||||
NLOHMANN_JSON_HAS_HELPER(key_type);
 | 
			
		||||
NLOHMANN_JSON_HAS_HELPER(value_type);
 | 
			
		||||
NLOHMANN_JSON_HAS_HELPER(iterator);
 | 
			
		||||
 | 
			
		||||
template<bool B, class RealType, class CompatibleObjectType>
 | 
			
		||||
struct is_compatible_object_type_impl : std::false_type {};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -402,8 +472,8 @@ struct is_compatible_object_type
 | 
			
		|||
{
 | 
			
		||||
    static auto constexpr value = is_compatible_object_type_impl <
 | 
			
		||||
                                  conjunction<negation<std::is_same<void, CompatibleObjectType>>,
 | 
			
		||||
                                  has_mapped_type<CompatibleObjectType>,
 | 
			
		||||
                                  has_key_type<CompatibleObjectType>>::value,
 | 
			
		||||
                                  is_detected<mapped_type_t, CompatibleObjectType>,
 | 
			
		||||
                                  is_detected<key_type_t, CompatibleObjectType>>::value,
 | 
			
		||||
                                  typename BasicJsonType::object_t, CompatibleObjectType >::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -412,7 +482,7 @@ struct is_compatible_string_type
 | 
			
		|||
{
 | 
			
		||||
    static auto constexpr value = is_compatible_string_type_impl <
 | 
			
		||||
                                  conjunction<negation<std::is_same<void, CompatibleStringType>>,
 | 
			
		||||
                                  has_value_type<CompatibleStringType>>::value,
 | 
			
		||||
                                  is_detected<value_type_t, CompatibleStringType>>::value,
 | 
			
		||||
                                  typename BasicJsonType::string_t, CompatibleStringType >::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -435,8 +505,8 @@ struct is_compatible_array_type
 | 
			
		|||
        negation<std::is_constructible<typename BasicJsonType::string_t,
 | 
			
		||||
        CompatibleArrayType>>,
 | 
			
		||||
        negation<is_basic_json_nested_type<BasicJsonType, CompatibleArrayType>>,
 | 
			
		||||
        has_value_type<CompatibleArrayType>,
 | 
			
		||||
        has_iterator<CompatibleArrayType>>::value;
 | 
			
		||||
        is_detected<value_type_t, CompatibleArrayType>,
 | 
			
		||||
        is_detected<iterator_t, CompatibleArrayType>>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<bool, typename, typename>
 | 
			
		||||
| 
						 | 
				
			
			@ -469,14 +539,11 @@ struct is_compatible_integer_type
 | 
			
		|||
template<typename BasicJsonType, typename T>
 | 
			
		||||
struct has_from_json
 | 
			
		||||
{
 | 
			
		||||
    // also check the return type of from_json
 | 
			
		||||
    template<typename U, typename = enable_if_t<std::is_same<void, decltype(uncvref_t<U>::from_json(
 | 
			
		||||
                 std::declval<BasicJsonType>(), std::declval<T&>()))>::value>>
 | 
			
		||||
    static int detect(U&&);
 | 
			
		||||
    static void detect(...);
 | 
			
		||||
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
 | 
			
		||||
 | 
			
		||||
    static constexpr bool value = std::is_integral<decltype(
 | 
			
		||||
                                      detect(std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
 | 
			
		||||
    static constexpr bool value =
 | 
			
		||||
        is_detected_exact<void, from_json_function, serializer,
 | 
			
		||||
        const BasicJsonType&, T&>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
 | 
			
		||||
| 
						 | 
				
			
			@ -484,28 +551,22 @@ struct has_from_json
 | 
			
		|||
template<typename BasicJsonType, typename T>
 | 
			
		||||
struct has_non_default_from_json
 | 
			
		||||
{
 | 
			
		||||
    template <
 | 
			
		||||
        typename U,
 | 
			
		||||
        typename = enable_if_t<std::is_same<
 | 
			
		||||
                                   T, decltype(uncvref_t<U>::from_json(std::declval<BasicJsonType>()))>::value >>
 | 
			
		||||
    static int detect(U&&);
 | 
			
		||||
    static void detect(...);
 | 
			
		||||
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
 | 
			
		||||
 | 
			
		||||
    static constexpr bool value = std::is_integral<decltype(detect(
 | 
			
		||||
                                      std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
 | 
			
		||||
    static constexpr bool value =
 | 
			
		||||
        is_detected_exact<T, from_json_function, serializer,
 | 
			
		||||
        const BasicJsonType&>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
 | 
			
		||||
template<typename BasicJsonType, typename T>
 | 
			
		||||
struct has_to_json
 | 
			
		||||
{
 | 
			
		||||
    template<typename U, typename = decltype(uncvref_t<U>::to_json(
 | 
			
		||||
                 std::declval<BasicJsonType&>(), std::declval<T>()))>
 | 
			
		||||
    static int detect(U&&);
 | 
			
		||||
    static void detect(...);
 | 
			
		||||
    using serializer = typename BasicJsonType::template json_serializer<T, void>;
 | 
			
		||||
 | 
			
		||||
    static constexpr bool value = std::is_integral<decltype(detect(
 | 
			
		||||
                                      std::declval<typename BasicJsonType::template json_serializer<T, void>>()))>::value;
 | 
			
		||||
    static constexpr bool value =
 | 
			
		||||
        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
 | 
			
		||||
        T>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename BasicJsonType, typename CompatibleCompleteType>
 | 
			
		||||
| 
						 | 
				
			
			@ -3562,76 +3623,6 @@ scan_number_done:
 | 
			
		|||
 | 
			
		||||
// #include <nlohmann/detail/meta/detected.hpp>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
// #include <nlohmann/detail/meta/void_t.hpp>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace nlohmann
 | 
			
		||||
{
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
template <typename ...Ts> struct make_void
 | 
			
		||||
{
 | 
			
		||||
    using type = void;
 | 
			
		||||
};
 | 
			
		||||
template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// http://en.cppreference.com/w/cpp/experimental/is_detected
 | 
			
		||||
namespace nlohmann
 | 
			
		||||
{
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
struct nonesuch
 | 
			
		||||
{
 | 
			
		||||
    nonesuch() = delete;
 | 
			
		||||
    ~nonesuch() = delete;
 | 
			
		||||
    nonesuch(nonesuch const&) = delete;
 | 
			
		||||
    void operator=(nonesuch const&) = delete;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Default,
 | 
			
		||||
          class AlwaysVoid,
 | 
			
		||||
          template <class...> class Op,
 | 
			
		||||
          class... Args>
 | 
			
		||||
struct detector
 | 
			
		||||
{
 | 
			
		||||
    using value_t = std::false_type;
 | 
			
		||||
    using type = Default;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Default, template <class...> class Op, class... Args>
 | 
			
		||||
struct detector<Default, void_t<Op<Args...>>, Op, Args...>
 | 
			
		||||
{
 | 
			
		||||
    using value_t = std::true_type;
 | 
			
		||||
    using type = Op<Args...>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <template <class...> class Op, class... Args>
 | 
			
		||||
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
 | 
			
		||||
 | 
			
		||||
template <template <class...> class Op, class... Args>
 | 
			
		||||
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
 | 
			
		||||
 | 
			
		||||
template <class Default, template <class...> class Op, class... Args>
 | 
			
		||||
using detected_or = detector<Default, void, Op, Args...>;
 | 
			
		||||
 | 
			
		||||
template <class Default, template <class...> class Op, class... Args>
 | 
			
		||||
using detected_or_t = typename detected_or<Default, Op, Args...>::type;
 | 
			
		||||
 | 
			
		||||
template <class Expected, template <class...> class Op, class... Args>
 | 
			
		||||
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
 | 
			
		||||
 | 
			
		||||
template <class To, template <class...> class Op, class... Args>
 | 
			
		||||
using is_detected_convertible =
 | 
			
		||||
    std::is_convertible<detected_t<Op, Args...>, To>;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// #include <nlohmann/detail/meta/type_traits.hpp>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -18902,7 +18893,6 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std
 | 
			
		|||
#undef JSON_HAS_CPP_17
 | 
			
		||||
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
 | 
			
		||||
#undef NLOHMANN_BASIC_JSON_TPL
 | 
			
		||||
#undef NLOHMANN_JSON_HAS_HELPER
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue