add alias templates to reduce boilerplate

This commit is contained in:
Théo DELRIEU 2016-10-18 23:45:58 +02:00 committed by Théo DELRIEU
parent fe628b585b
commit d54d6bb84c

View file

@ -117,6 +117,17 @@ namespace nlohmann
template <typename T, typename = void> template <typename T, typename = void>
struct json_traits; struct json_traits;
// alias templates to reduce boilerplate
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
template <typename T>
using remove_cv_t = typename std::remove_cv<T>::type;
template <typename T>
using remove_reference_t = typename std::remove_reference<T>::type;
// TODO update this doc
/*! /*!
@brief unnamed namespace with internal helper functions @brief unnamed namespace with internal helper functions
@since version 1.0.0 @since version 1.0.0
@ -1393,15 +1404,11 @@ class basic_json
// auto j = json{{"a", json(not_equality_comparable{})}}; // auto j = json{{"a", json(not_equality_comparable{})}};
// //
// we can remove this constraint though, since lots of ctor are not explicit already // we can remove this constraint though, since lots of ctor are not explicit already
template < template <typename T, typename = enable_if_t<detail::has_json_traits<
typename T, remove_cv_t<remove_reference_t<T>>>::value>>
typename =
typename std::enable_if<detail::has_json_traits<typename std::remove_cv<
typename std::remove_reference<T>::type>::type>::value>::type>
explicit basic_json(T &&val) explicit basic_json(T &&val)
: basic_json(json_traits<typename std::remove_cv< : basic_json(json_traits<remove_cv_t<remove_reference_t<T>>>::to_json(
typename std::remove_reference<T>::type>::type>:: std::forward<T>(val))) {}
to_json(std::forward<T>(val))) {}
/*! /*!
@brief create a string (explicit) @brief create a string (explicit)
@ -1418,13 +1425,14 @@ class basic_json
@sa @ref basic_json(const typename string_t::value_type*) -- create a @sa @ref basic_json(const typename string_t::value_type*) -- create a
string value from a character pointer string value from a character pointer
@sa @ref basic_json(const CompatibleStringType&) -- create a string @sa @ref basic_json(const CompatibleStringType&) -- create a string value
value
from a compatible string container from a compatible string container
@since version 1.0.0 @since version 1.0.0
*/ */
basic_json(const string_t &val) : m_type(value_t::string), m_value(val) { basic_json(const string_t& val)
: m_type(value_t::string), m_value(val)
{
assert_invariant(); assert_invariant();
} }
@ -2763,17 +2771,12 @@ class basic_json
// get_impl overload chosen if json_traits struct is specialized for type T // get_impl overload chosen if json_traits struct is specialized for type T
// simply returns json_traits<T>::from_json(*this); // simply returns json_traits<T>::from_json(*this);
// TODO add alias templates (enable_if_t etc) template <typename T, typename = enable_if_t<detail::has_json_traits<
template < remove_cv_t<remove_reference_t<T>>>::value>>
typename T, auto get_impl(T *) const
typename = typename std::enable_if< -> decltype(json_traits<remove_cv_t<remove_reference_t<T>>>::from_json(
detail::has_json_traits<typename std::remove_cv< std::declval<basic_json>())) {
typename std::remove_reference<T>::type>::type>::value>::type> return json_traits<remove_cv_t<remove_reference_t<T>>>::from_json(*this);
auto get_impl(T *) const -> decltype(
json_traits<typename std::remove_cv<typename std::remove_reference<
T>::type>::type>::from_json(std::declval<basic_json>())) {
return json_traits<typename std::remove_cv<
typename std::remove_reference<T>::type>::type>::from_json(*this);
} }
// this one is quite atrocious // this one is quite atrocious
@ -2781,31 +2784,34 @@ class basic_json
// I chose to prefer the json_traits specialization if it exists, since it's a more advanced use. // I chose to prefer the json_traits specialization if it exists, since it's a more advanced use.
// But we can of course change this behaviour // But we can of course change this behaviour
template <typename T> template <typename T>
auto get_impl(T *) const -> typename std::enable_if< auto get_impl(T *) const
not detail::has_json_traits<typename std::remove_cv<T>::type>::value, -> enable_if_t<not detail::has_json_traits<remove_cv_t<T>>::value,
typename std::remove_cv<typename std::remove_reference< remove_cv_t<remove_reference_t<decltype(
decltype(::nlohmann::from_json(std::declval<basic_json>(), ::nlohmann::from_json(std::declval<basic_json>(),
std::declval<T &>()), std::declval<T &>()),
std::declval<T>())>::type>::type>::type std::declval<T>())>>>
{ {
typename std::remove_cv<typename std::remove_reference<T>::type>::type remove_cv_t<T> ret;
ret; // I guess this output parameter is the only way to get ADL
// Even if users can use the get<T> method to have a more 'functional' behaviour
// i.e. having a return type, could there be a way to have the same behaviour with from_json?
// e.g. auto t = nlohmann::from_json<T>(json{});
// this seems to require variable templates though... (at least it did when I tried to implement it)
::nlohmann::from_json(*this, ret); ::nlohmann::from_json(*this, ret);
return ret; return ret;
} }
/// get an object (explicit) template<class T, typename std::enable_if<
template <class T, std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
typename std::enable_if< std::is_convertible<basic_json_t, typename T::mapped_type>::value, int>::type = 0>
std::is_convertible<typename object_t::key_type, T get_impl(T*) const
typename T::key_type>::value and {
std::is_convertible<basic_json_t, if (is_object())
typename T::mapped_type>::value, {
int>::type = 0>
T get_impl(T *) const {
if (is_object()) {
return T(m_value.object->begin(), m_value.object->end()); return T(m_value.object->begin(), m_value.object->end());
} else { }
else
{
JSON_THROW(std::domain_error("type must be object, but is " + type_name())); JSON_THROW(std::domain_error("type must be object, but is " + type_name()));
} }