Unverified Commit d3428b35 by Niels Lohmann Committed by GitHub

Merge pull request #1228 from theodelrieu/remove_static_asserts

Remove static asserts
parents eb30ff06 aea648bb
...@@ -20,8 +20,10 @@ struct adl_serializer ...@@ -20,8 +20,10 @@ struct adl_serializer
@param[in,out] val value to write to @param[in,out] val value to write to
*/ */
template<typename BasicJsonType, typename ValueType> template<typename BasicJsonType, typename ValueType>
static void from_json(BasicJsonType&& j, ValueType& val) noexcept( static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val))) -> decltype(
::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void()
)
{ {
::nlohmann::from_json(std::forward<BasicJsonType>(j), val); ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
} }
...@@ -35,9 +37,11 @@ struct adl_serializer ...@@ -35,9 +37,11 @@ struct adl_serializer
@param[in,out] j JSON value to write to @param[in,out] j JSON value to write to
@param[in] val value to read from @param[in] val value to read from
*/ */
template<typename BasicJsonType, typename ValueType> template <typename BasicJsonType, typename ValueType>
static void to_json(BasicJsonType& j, ValueType&& val) noexcept( static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val)))) noexcept(::nlohmann::to_json(j, std::forward<ValueType>(val))))
-> decltype(::nlohmann::to_json(j, std::forward<ValueType>(val)),
void())
{ {
::nlohmann::to_json(j, std::forward<ValueType>(val)); ::nlohmann::to_json(j, std::forward<ValueType>(val));
} }
......
...@@ -127,16 +127,6 @@ void from_json(const BasicJsonType& j, EnumType& e) ...@@ -127,16 +127,6 @@ void from_json(const BasicJsonType& j, EnumType& e)
e = static_cast<EnumType>(val); e = static_cast<EnumType>(val);
} }
template<typename BasicJsonType>
void from_json(const BasicJsonType& j, typename BasicJsonType::array_t& arr)
{
if (JSON_UNLIKELY(not j.is_array()))
{
JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name())));
}
arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
}
// forward_list doesn't have an insert method // forward_list doesn't have an insert method
template<typename BasicJsonType, typename T, typename Allocator, template<typename BasicJsonType, typename T, typename Allocator,
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0> enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
...@@ -166,24 +156,28 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l) ...@@ -166,24 +156,28 @@ void from_json(const BasicJsonType& j, std::valarray<T>& l)
std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l)); std::copy(j.m_value.array->begin(), j.m_value.array->end(), std::begin(l));
} }
template<typename BasicJsonType, typename CompatibleArrayType> template<typename BasicJsonType>
void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/) void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
{ {
using std::end; arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
}
std::transform(j.begin(), j.end(), template <typename BasicJsonType, typename T, std::size_t N>
std::inserter(arr, end(arr)), [](const BasicJsonType & i) auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
priority_tag<2> /*unused*/)
-> decltype(j.template get<T>(), void())
{
for (std::size_t i = 0; i < N; ++i)
{ {
// get<BasicJsonType>() returns *this, this won't call a from_json arr[i] = j.at(i).template get<T>();
// method when value_type is BasicJsonType }
return i.template get<typename CompatibleArrayType::value_type>();
});
} }
template<typename BasicJsonType, typename CompatibleArrayType> template<typename BasicJsonType, typename CompatibleArrayType>
auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/) auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
-> decltype( -> decltype(
arr.reserve(std::declval<typename CompatibleArrayType::size_type>()), arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
j.template get<typename CompatibleArrayType::value_type>(),
void()) void())
{ {
using std::end; using std::end;
...@@ -198,25 +192,34 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio ...@@ -198,25 +192,34 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
}); });
} }
template<typename BasicJsonType, typename T, std::size_t N> template <typename BasicJsonType, typename CompatibleArrayType>
void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/) void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr,
priority_tag<0> /*unused*/)
{ {
for (std::size_t i = 0; i < N; ++i) using std::end;
std::transform(
j.begin(), j.end(), std::inserter(arr, end(arr)),
[](const BasicJsonType & i)
{ {
arr[i] = j.at(i).template get<T>(); // get<BasicJsonType>() returns *this, this won't call a from_json
} // method when value_type is BasicJsonType
return i.template get<typename CompatibleArrayType::value_type>();
});
} }
template < template <typename BasicJsonType, typename CompatibleArrayType,
typename BasicJsonType, typename CompatibleArrayType, enable_if_t <
enable_if_t < is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and not is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value and
not std::is_same<typename BasicJsonType::array_t, not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
CompatibleArrayType>::value and not is_basic_json<CompatibleArrayType>::value,
std::is_constructible < int > = 0 >
BasicJsonType, typename CompatibleArrayType::value_type >::value,
int > = 0 > auto from_json(const BasicJsonType& j, CompatibleArrayType& arr)
void from_json(const BasicJsonType& j, CompatibleArrayType& arr) -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
j.template get<typename CompatibleArrayType::value_type>(),
void())
{ {
if (JSON_UNLIKELY(not j.is_array())) if (JSON_UNLIKELY(not j.is_array()))
{ {
...@@ -224,7 +227,7 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr) ...@@ -224,7 +227,7 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
std::string(j.type_name()))); std::string(j.type_name())));
} }
from_json_array_impl(j, arr, priority_tag<2> {}); from_json_array_impl(j, arr, priority_tag<3> {});
} }
template<typename BasicJsonType, typename CompatibleObjectType, template<typename BasicJsonType, typename CompatibleObjectType,
...@@ -347,35 +350,13 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE ...@@ -347,35 +350,13 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
struct from_json_fn struct from_json_fn
{ {
private:
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
auto call(const BasicJsonType& j, T& val, priority_tag<1> /*unused*/) const auto operator()(const BasicJsonType& j, T& val) const
noexcept(noexcept(from_json(j, val))) noexcept(noexcept(from_json(j, val)))
-> decltype(from_json(j, val), void()) -> decltype(from_json(j, val), void())
{ {
return from_json(j, val); return from_json(j, val);
} }
template<typename BasicJsonType, typename T>
void call(const BasicJsonType& /*unused*/, T& /*unused*/, priority_tag<0> /*unused*/) const noexcept
{
static_assert(sizeof(BasicJsonType) == 0,
"could not find from_json() method in T's namespace");
#ifdef _MSC_VER
// MSVC does not show a stacktrace for the above assert
using decayed = uncvref_t<T>;
static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
"forcing MSVC stacktrace to show which T we're talking about.");
#endif
}
public:
template<typename BasicJsonType, typename T>
void operator()(const BasicJsonType& j, T& val) const
noexcept(noexcept(std::declval<from_json_fn>().call(j, val, priority_tag<1> {})))
{
return call(j, val, priority_tag<1> {});
}
}; };
} }
......
...@@ -248,10 +248,14 @@ void to_json(BasicJsonType& j, const std::vector<bool>& e) ...@@ -248,10 +248,14 @@ void to_json(BasicJsonType& j, const std::vector<bool>& e)
external_constructor<value_t::array>::construct(j, e); external_constructor<value_t::array>::construct(j, e);
} }
template<typename BasicJsonType, typename CompatibleArrayType, template <typename BasicJsonType, typename CompatibleArrayType,
enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or enable_if_t<is_compatible_array_type<BasicJsonType,
std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value, CompatibleArrayType>::value and
int> = 0> not is_compatible_object_type<
BasicJsonType, CompatibleArrayType>::value and
not is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value and
not is_basic_json<CompatibleArrayType>::value,
int> = 0>
void to_json(BasicJsonType& j, const CompatibleArrayType& arr) void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
{ {
external_constructor<value_t::array>::construct(j, arr); external_constructor<value_t::array>::construct(j, arr);
...@@ -271,7 +275,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) ...@@ -271,7 +275,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
} }
template<typename BasicJsonType, typename CompatibleObjectType, template<typename BasicJsonType, typename CompatibleObjectType,
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value, int> = 0> enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value and not is_basic_json<CompatibleObjectType>::value, int> = 0>
void to_json(BasicJsonType& j, const CompatibleObjectType& obj) void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
{ {
external_constructor<value_t::object>::construct(j, obj); external_constructor<value_t::object>::construct(j, obj);
...@@ -283,9 +287,12 @@ void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) ...@@ -283,9 +287,12 @@ void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
external_constructor<value_t::object>::construct(j, std::move(obj)); external_constructor<value_t::object>::construct(j, std::move(obj));
} }
template<typename BasicJsonType, typename T, std::size_t N, template <
enable_if_t<not std::is_constructible<typename BasicJsonType::string_t, T (&)[N]>::value, int> = 0> typename BasicJsonType, typename T, std::size_t N,
void to_json(BasicJsonType& j, T (&arr)[N]) enable_if_t<not std::is_constructible<typename BasicJsonType::string_t,
const T (&)[N]>::value,
int> = 0 >
void to_json(BasicJsonType& j, const T (&arr)[N])
{ {
external_constructor<value_t::array>::construct(j, arr); external_constructor<value_t::array>::construct(j, arr);
} }
...@@ -318,35 +325,12 @@ void to_json(BasicJsonType& j, const std::tuple<Args...>& t) ...@@ -318,35 +325,12 @@ void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
struct to_json_fn struct to_json_fn
{ {
private:
template<typename BasicJsonType, typename T> template<typename BasicJsonType, typename T>
auto call(BasicJsonType& j, T&& val, priority_tag<1> /*unused*/) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
-> decltype(to_json(j, std::forward<T>(val)), void()) -> decltype(to_json(j, std::forward<T>(val)), void())
{ {
return to_json(j, std::forward<T>(val)); return to_json(j, std::forward<T>(val));
} }
template<typename BasicJsonType, typename T>
void call(BasicJsonType& /*unused*/, T&& /*unused*/, priority_tag<0> /*unused*/) const noexcept
{
static_assert(sizeof(BasicJsonType) == 0,
"could not find to_json() method in T's namespace");
#ifdef _MSC_VER
// MSVC does not show a stacktrace for the above assert
using decayed = uncvref_t<T>;
static_assert(sizeof(typename decayed::force_msvc_stacktrace) == 0,
"forcing MSVC stacktrace to show which T we're talking about.");
#endif
}
public:
template<typename BasicJsonType, typename T>
void operator()(BasicJsonType& j, T&& val) const
noexcept(noexcept(std::declval<to_json_fn>().call(j, std::forward<T>(val), priority_tag<1> {})))
{
return call(j, std::forward<T>(val), priority_tag<1> {});
}
}; };
} }
......
...@@ -102,22 +102,3 @@ ...@@ -102,22 +102,3 @@
basic_json<ObjectType, ArrayType, StringType, BooleanType, \ basic_json<ObjectType, ArrayType, StringType, BooleanType, \
NumberIntegerType, NumberUnsignedType, NumberFloatType, \ NumberIntegerType, NumberUnsignedType, NumberFloatType, \
AllocatorType, JSONSerializer> 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; \
}
...@@ -20,4 +20,3 @@ ...@@ -20,4 +20,3 @@
#undef JSON_HAS_CPP_17 #undef JSON_HAS_CPP_17
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
#undef NLOHMANN_BASIC_JSON_TPL #undef NLOHMANN_BASIC_JSON_TPL
#undef NLOHMANN_JSON_HAS_HELPER
...@@ -46,26 +46,6 @@ template<> struct make_index_sequence<1> : index_sequence<0> {}; ...@@ -46,26 +46,6 @@ template<> struct make_index_sequence<1> : index_sequence<0> {};
template<typename... Ts> template<typename... Ts>
using index_sequence_for = make_index_sequence<sizeof...(Ts)>; using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
/*
Implementation of two C++17 constructs: conjunction, negation. This is needed
to avoid evaluating all the traits in a condition
For example: not std::is_same<void, T>::value and has_value_type<T>::value
will not compile when T = void (on MSVC at least). Whereas
conjunction<negation<std::is_same<void, T>>, has_value_type<T>>::value will
stop evaluating if negation<...>::value == false
Please note that those constructs must be used with caution, since symbols can
become very long quickly (which can slow down compilation and cause MSVC
internal compiler errors). Only use it when you have to (see example ahead).
*/
template<class...> struct conjunction : std::true_type {};
template<class B1> struct conjunction<B1> : B1 {};
template<class B1, class... Bn>
struct conjunction<B1, Bn...> : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
template<class B> struct negation : std::integral_constant<bool, not B::value> {};
// dispatch utility (taken from ranges-v3) // dispatch utility (taken from ranges-v3)
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {}; template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {}; template<> struct priority_tag<0> {};
......
...@@ -4,7 +4,10 @@ namespace nlohmann ...@@ -4,7 +4,10 @@ namespace nlohmann
{ {
namespace detail namespace detail
{ {
template <typename...> template <typename ...Ts> struct make_void
using void_t = void; {
using type = void;
};
template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
} }
} }
...@@ -1243,7 +1243,7 @@ class basic_json ...@@ -1243,7 +1243,7 @@ class basic_json
template <typename CompatibleType, template <typename CompatibleType,
typename U = detail::uncvref_t<CompatibleType>, typename U = detail::uncvref_t<CompatibleType>,
detail::enable_if_t< detail::enable_if_t<
detail::is_compatible_type<basic_json_t, U>::value, int> = 0> not detail::is_basic_json<U>::value and detail::is_compatible_type<basic_json_t, U>::value, int> = 0>
basic_json(CompatibleType && val) noexcept(noexcept( basic_json(CompatibleType && val) noexcept(noexcept(
JSONSerializer<U>::to_json(std::declval<basic_json_t&>(), JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
std::forward<CompatibleType>(val)))) std::forward<CompatibleType>(val))))
......
...@@ -317,8 +317,8 @@ TEST_CASE("object inspection") ...@@ -317,8 +317,8 @@ TEST_CASE("object inspection")
SECTION("round trips") SECTION("round trips")
{ {
for (const auto& s : for (const auto& s :
{"3.141592653589793", "1000000000000000010E5" {"3.141592653589793", "1000000000000000010E5"
}) })
{ {
json j1 = json::parse(s); json j1 = json::parse(s);
std::string s1 = j1.dump(); std::string s1 = j1.dump();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment