Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitHub Actions <action@github.com>2020-06-28 14:43:52 +0300
committerGitHub Actions <action@github.com>2020-06-28 14:43:52 +0300
commita6cb432baae54b4e9caadc65c3f3f277bc5538ca (patch)
tree78b290d2f2c75aa6bc7ec77f48122677bae3ac17
parentd8391a6880f5410882cbcc242b22a8dc16438513 (diff)
Upstream release v3.3.0v3.3.0
-rw-r--r--README.md2
-rw-r--r--include/nlohmann/json.hpp984
2 files changed, 501 insertions, 485 deletions
diff --git a/README.md b/README.md
index 3b3fe5c..0cb8cff 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ include(FetchContent)
FetchContent_Declare(json
GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohman_json
- GIT_TAG v3.2.0)
+ GIT_TAG v3.3.0)
FetchContent_GetProperties(json)
if(NOT json_POPULATED)
diff --git a/include/nlohmann/json.hpp b/include/nlohmann/json.hpp
index b80386f..c40620a 100644
--- a/include/nlohmann/json.hpp
+++ b/include/nlohmann/json.hpp
@@ -1,7 +1,7 @@
/*
__ _____ _____ _____
__| | __| | | | JSON for Modern C++
-| | |__ | | | | | | version 3.2.0
+| | |__ | | | | | | version 3.3.0
|_____|_____|_____|_|___| https://github.com/nlohmann/json
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
@@ -31,7 +31,7 @@ SOFTWARE.
#define NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_VERSION_MAJOR 3
-#define NLOHMANN_JSON_VERSION_MINOR 2
+#define NLOHMANN_JSON_VERSION_MINOR 3
#define NLOHMANN_JSON_VERSION_PATCH 0
#include <algorithm> // all_of, find, for_each
@@ -125,7 +125,7 @@ using json = basic_json<>;
#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
#endif
#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
- #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40900
+ #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
#endif
#endif
@@ -177,6 +177,7 @@ using json = basic_json<>;
#if defined(JSON_CATCH_USER)
#undef JSON_CATCH
#define JSON_CATCH JSON_CATCH_USER
+ #undef JSON_INTERNAL_CATCH
#define JSON_INTERNAL_CATCH JSON_CATCH_USER
#endif
#if defined(JSON_INTERNAL_CATCH_USER)
@@ -217,27 +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 { \
- private: \
- template<typename U, typename = typename U::type> \
- static int detect(U &&); \
- static void detect(...); \
- public: \
- static constexpr bool value = \
- std::is_integral<decltype(detect(std::declval<T>()))>::value; \
- }
-
// #include <nlohmann/detail/meta/cpp_future.hpp>
@@ -287,26 +267,6 @@ template<> struct make_index_sequence<1> : index_sequence<0> {};
template<typename... 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)
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
template<> struct priority_tag<0> {};
@@ -335,6 +295,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>
@@ -359,9 +391,64 @@ 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 difference_type_t = typename T::difference_type;
+
+template <typename T>
+using pointer_t = typename T::pointer;
+
+template <typename T>
+using reference_t = typename T::reference;
+
+template <typename T>
+using iterator_category_t = typename T::iterator_category;
+
+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>()...));
+
+template <typename T, typename U>
+using get_template_function = decltype(std::declval<T>().template get<U>());
+
+///////////////////
+// is_ functions //
+///////////////////
+
+template <typename T, typename = void>
+struct is_iterator_traits : std::false_type {};
+
+template <typename T>
+struct is_iterator_traits<std::iterator_traits<T>>
+{
+ private:
+ using traits = std::iterator_traits<T>;
+
+ public:
+ static constexpr auto value =
+ is_detected<value_type_t, traits>::value &&
+ is_detected<difference_type_t, traits>::value &&
+ is_detected<pointer_t, traits>::value &&
+ is_detected<iterator_category_t, traits>::value &&
+ is_detected<reference_t, traits>::value;
+};
// source: https://stackoverflow.com/a/37193089/4116453
@@ -371,166 +458,155 @@ 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>
+template <typename BasicJsonType, typename CompatibleObjectType,
+ typename = void>
struct is_compatible_object_type_impl : std::false_type {};
-template<class RealType, class CompatibleObjectType>
-struct is_compatible_object_type_impl<true, RealType, CompatibleObjectType>
+template <typename BasicJsonType, typename CompatibleObjectType>
+struct is_compatible_object_type_impl <
+ BasicJsonType, CompatibleObjectType,
+ enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value and
+ is_detected<key_type_t, CompatibleObjectType>::value >>
{
- static constexpr auto value =
- std::is_constructible<typename RealType::key_type, typename CompatibleObjectType::key_type>::value and
- std::is_constructible<typename RealType::mapped_type, typename CompatibleObjectType::mapped_type>::value;
-};
-template<bool B, class RealType, class CompatibleStringType>
-struct is_compatible_string_type_impl : std::false_type {};
+ using object_t = typename BasicJsonType::object_t;
-template<class RealType, class CompatibleStringType>
-struct is_compatible_string_type_impl<true, RealType, CompatibleStringType>
-{
- static constexpr auto value =
- std::is_same<typename RealType::value_type, typename CompatibleStringType::value_type>::value and
- std::is_constructible<RealType, CompatibleStringType>::value;
+ // macOS's is_constructible does not play well with nonesuch...
+ static constexpr bool value =
+ std::is_constructible<typename object_t::key_type,
+ typename CompatibleObjectType::key_type>::value and
+ std::is_constructible<typename object_t::mapped_type,
+ typename CompatibleObjectType::mapped_type>::value;
};
-template<class BasicJsonType, class CompatibleObjectType>
+template <typename BasicJsonType, typename CompatibleObjectType>
struct is_compatible_object_type
+ : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
+
+template <typename BasicJsonType, typename CompatibleStringType,
+ typename = void>
+struct is_compatible_string_type_impl : std::false_type {};
+
+template <typename BasicJsonType, typename CompatibleStringType>
+struct is_compatible_string_type_impl <
+ BasicJsonType, CompatibleStringType,
+ enable_if_t<is_detected_exact<typename BasicJsonType::string_t::value_type,
+ value_type_t, CompatibleStringType>::value >>
{
- 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,
- typename BasicJsonType::object_t, CompatibleObjectType >::value;
+ static constexpr auto value =
+ std::is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
};
-template<class BasicJsonType, class CompatibleStringType>
+template <typename BasicJsonType, typename CompatibleStringType>
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,
- typename BasicJsonType::string_t, CompatibleStringType >::value;
-};
+ : is_compatible_string_type_impl<BasicJsonType, CompatibleStringType> {};
-template<typename BasicJsonType, typename T>
-struct is_basic_json_nested_type
+template <typename BasicJsonType, typename CompatibleArrayType, typename = void>
+struct is_compatible_array_type_impl : std::false_type {};
+
+template <typename BasicJsonType, typename CompatibleArrayType>
+struct is_compatible_array_type_impl <
+ BasicJsonType, CompatibleArrayType,
+ enable_if_t<is_detected<value_type_t, CompatibleArrayType>::value and
+ is_detected<iterator_t, CompatibleArrayType>::value >>
{
- static auto constexpr value = std::is_same<T, typename BasicJsonType::iterator>::value or
- std::is_same<T, typename BasicJsonType::const_iterator>::value or
- std::is_same<T, typename BasicJsonType::reverse_iterator>::value or
- std::is_same<T, typename BasicJsonType::const_reverse_iterator>::value;
+ // This is needed because json_reverse_iterator has a ::iterator type...
+ // Therefore it is detected as a CompatibleArrayType.
+ // The real fix would be to have an Iterable concept.
+ static constexpr bool value = not is_iterator_traits<std::iterator_traits<CompatibleArrayType>>::value;
};
-template<class BasicJsonType, class CompatibleArrayType>
+template <typename BasicJsonType, typename CompatibleArrayType>
struct is_compatible_array_type
-{
- static auto constexpr value =
- conjunction<negation<std::is_same<void, CompatibleArrayType>>,
- negation<is_compatible_object_type<
- BasicJsonType, CompatibleArrayType>>,
- 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_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
-template<bool, typename, typename>
+template <typename RealIntegerType, typename CompatibleNumberIntegerType,
+ typename = void>
struct is_compatible_integer_type_impl : std::false_type {};
-template<typename RealIntegerType, typename CompatibleNumberIntegerType>
-struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIntegerType>
+template <typename RealIntegerType, typename CompatibleNumberIntegerType>
+struct is_compatible_integer_type_impl <
+ RealIntegerType, CompatibleNumberIntegerType,
+ enable_if_t<std::is_integral<RealIntegerType>::value and
+ std::is_integral<CompatibleNumberIntegerType>::value and
+ not std::is_same<bool, CompatibleNumberIntegerType>::value >>
{
// is there an assert somewhere on overflows?
using RealLimits = std::numeric_limits<RealIntegerType>;
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
static constexpr auto value =
- std::is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value and
+ std::is_constructible<RealIntegerType,
+ CompatibleNumberIntegerType>::value and
CompatibleLimits::is_integer and
RealLimits::is_signed == CompatibleLimits::is_signed;
};
-template<typename RealIntegerType, typename CompatibleNumberIntegerType>
+template <typename RealIntegerType, typename CompatibleNumberIntegerType>
struct is_compatible_integer_type
-{
- static constexpr auto value =
- is_compatible_integer_type_impl <
- std::is_integral<CompatibleNumberIntegerType>::value and
- not std::is_same<bool, CompatibleNumberIntegerType>::value,
- RealIntegerType, CompatibleNumberIntegerType > ::value;
-};
+ : is_compatible_integer_type_impl<RealIntegerType,
+ CompatibleNumberIntegerType> {};
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
-template<typename BasicJsonType, typename T>
-struct has_from_json
+template <typename BasicJsonType, typename T, typename = void>
+struct has_from_json : std::false_type {};
+
+template <typename BasicJsonType, typename T>
+struct has_from_json<BasicJsonType, T,
+ enable_if_t<not is_basic_json<T>::value>>
{
- private:
- // 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>;
- public:
- 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
// this overload is used for non-default-constructible user-defined-types
+template <typename BasicJsonType, typename T, typename = void>
+struct has_non_default_from_json : std::false_type {};
+
template<typename BasicJsonType, typename T>
-struct has_non_default_from_json
+struct has_non_default_from_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
{
- private:
- 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>;
- public:
- 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
+// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
+template <typename BasicJsonType, typename T, typename = void>
+struct has_to_json : std::false_type {};
+
+template <typename BasicJsonType, typename T>
+struct has_to_json<BasicJsonType, T, enable_if_t<not is_basic_json<T>::value>>
{
- private:
- 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>;
- public:
- 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>
-struct is_compatible_complete_type
+template <typename BasicJsonType, typename CompatibleType, typename = void>
+struct is_compatible_type_impl: std::false_type {};
+
+template <typename BasicJsonType, typename CompatibleType>
+struct is_compatible_type_impl <
+ BasicJsonType, CompatibleType,
+ enable_if_t<is_complete_type<CompatibleType>::value >>
{
static constexpr bool value =
- not std::is_base_of<std::istream, CompatibleCompleteType>::value and
- not is_basic_json<CompatibleCompleteType>::value and
- not is_basic_json_nested_type<BasicJsonType, CompatibleCompleteType>::value and
- has_to_json<BasicJsonType, CompatibleCompleteType>::value;
+ has_to_json<BasicJsonType, CompatibleType>::value;
};
template <typename BasicJsonType, typename CompatibleType>
struct is_compatible_type
- : conjunction<is_complete_type<CompatibleType>,
- is_compatible_complete_type<BasicJsonType, CompatibleType>>
-{
-};
+ : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
}
}
@@ -1079,16 +1155,6 @@ void from_json(const BasicJsonType& j, EnumType& e)
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
template<typename BasicJsonType, typename T, typename Allocator,
enable_if_t<std::is_convertible<BasicJsonType, T>::value, int> = 0>
@@ -1118,24 +1184,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));
}
-template<typename BasicJsonType, typename CompatibleArrayType>
-void from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<0> /*unused*/)
+template<typename BasicJsonType>
+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(),
- std::inserter(arr, end(arr)), [](const BasicJsonType & i)
+template <typename BasicJsonType, typename T, std::size_t N>
+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
- // method when value_type is BasicJsonType
- return i.template get<typename CompatibleArrayType::value_type>();
- });
+ arr[i] = j.at(i).template get<T>();
+ }
}
template<typename BasicJsonType, typename CompatibleArrayType>
auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, priority_tag<1> /*unused*/)
-> decltype(
arr.reserve(std::declval<typename CompatibleArrayType::size_type>()),
+ j.template get<typename CompatibleArrayType::value_type>(),
void())
{
using std::end;
@@ -1150,25 +1220,34 @@ auto from_json_array_impl(const BasicJsonType& j, CompatibleArrayType& arr, prio
});
}
-template<typename BasicJsonType, typename T, std::size_t N>
-void from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/)
+template <typename BasicJsonType, typename CompatibleArrayType>
+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 <
- typename BasicJsonType, typename CompatibleArrayType,
- enable_if_t <
- is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
- not std::is_same<typename BasicJsonType::array_t,
- CompatibleArrayType>::value and
- std::is_constructible <
- BasicJsonType, typename CompatibleArrayType::value_type >::value,
- int > = 0 >
-void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
+template <typename BasicJsonType, typename CompatibleArrayType,
+ enable_if_t <
+ is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value and
+ 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 >
+
+auto 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()))
{
@@ -1176,7 +1255,7 @@ void from_json(const BasicJsonType& j, CompatibleArrayType& arr)
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,
@@ -1299,35 +1378,13 @@ void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyE
struct from_json_fn
{
- private:
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)))
-> decltype(from_json(j, val), void())
{
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> {});
- }
};
}
@@ -1724,10 +1781,14 @@ void to_json(BasicJsonType& j, const std::vector<bool>& e)
external_constructor<value_t::array>::construct(j, e);
}
-template<typename BasicJsonType, typename CompatibleArrayType,
- enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value or
- std::is_same<typename BasicJsonType::array_t, CompatibleArrayType>::value,
- int> = 0>
+template <typename BasicJsonType, typename CompatibleArrayType,
+ enable_if_t<is_compatible_array_type<BasicJsonType,
+ CompatibleArrayType>::value and
+ 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)
{
external_constructor<value_t::array>::construct(j, arr);
@@ -1747,7 +1808,7 @@ void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
}
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)
{
external_constructor<value_t::object>::construct(j, obj);
@@ -1759,9 +1820,12 @@ void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
external_constructor<value_t::object>::construct(j, std::move(obj));
}
-template<typename BasicJsonType, typename T, std::size_t N,
- enable_if_t<not std::is_constructible<typename BasicJsonType::string_t, T (&)[N]>::value, int> = 0>
-void to_json(BasicJsonType& j, T (&arr)[N])
+template <
+ typename BasicJsonType, typename T, std::size_t 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);
}
@@ -1794,35 +1858,12 @@ void to_json(BasicJsonType& j, const std::tuple<Args...>& t)
struct to_json_fn
{
- private:
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())
{
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> {});
- }
};
}
@@ -1952,38 +1993,66 @@ class input_buffer_adapter : public input_adapter_protocol
const char* const limit;
};
-template<typename WideStringType>
-class wide_string_input_adapter : public input_adapter_protocol
+template<typename WideStringType, size_t T>
+struct wide_string_input_helper
{
- public:
- explicit wide_string_input_adapter(const WideStringType& w) : str(w) {}
-
- std::char_traits<char>::int_type get_character() noexcept override
+ // UTF-32
+ static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
{
- // check if buffer needs to be filled
- if (utf8_bytes_index == utf8_bytes_filled)
+ utf8_bytes_index = 0;
+
+ if (current_wchar == str.size())
{
- if (sizeof(typename WideStringType::value_type) == 2)
+ utf8_bytes[0] = std::char_traits<char>::eof();
+ utf8_bytes_filled = 1;
+ }
+ else
+ {
+ // get the current character
+ const int wc = static_cast<int>(str[current_wchar++]);
+
+ // UTF-32 to UTF-8 encoding
+ if (wc < 0x80)
{
- fill_buffer_utf16();
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
+ }
+ else if (wc <= 0x7FF)
+ {
+ utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
+ utf8_bytes[1] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 2;
+ }
+ else if (wc <= 0xFFFF)
+ {
+ utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
+ utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
+ utf8_bytes[2] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 3;
+ }
+ else if (wc <= 0x10FFFF)
+ {
+ utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);
+ utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
+ utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
+ utf8_bytes[3] = 0x80 | (wc & 0x3F);
+ utf8_bytes_filled = 4;
}
else
{
- fill_buffer_utf32();
+ // unknown character
+ utf8_bytes[0] = wc;
+ utf8_bytes_filled = 1;
}
-
- assert(utf8_bytes_filled > 0);
- assert(utf8_bytes_index == 0);
}
-
- // use buffer
- assert(utf8_bytes_filled > 0);
- assert(utf8_bytes_index < utf8_bytes_filled);
- return utf8_bytes[utf8_bytes_index++];
}
+};
- private:
- void fill_buffer_utf16()
+template<typename WideStringType>
+struct wide_string_input_helper<WideStringType, 2>
+{
+ // UTF-16
+ static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
{
utf8_bytes_index = 0;
@@ -2038,58 +2107,38 @@ class wide_string_input_adapter : public input_adapter_protocol
}
}
}
+};
- void fill_buffer_utf32()
- {
- utf8_bytes_index = 0;
+template<typename WideStringType>
+class wide_string_input_adapter : public input_adapter_protocol
+{
+ public:
+ explicit wide_string_input_adapter(const WideStringType& w) : str(w) {}
- if (current_wchar == str.size())
- {
- utf8_bytes[0] = std::char_traits<char>::eof();
- utf8_bytes_filled = 1;
- }
- else
+ std::char_traits<char>::int_type get_character() noexcept override
+ {
+ // check if buffer needs to be filled
+ if (utf8_bytes_index == utf8_bytes_filled)
{
- // get the current character
- const int wc = static_cast<int>(str[current_wchar++]);
+ fill_buffer<sizeof(typename WideStringType::value_type)>();
- // UTF-32 to UTF-8 encoding
- if (wc < 0x80)
- {
- utf8_bytes[0] = wc;
- utf8_bytes_filled = 1;
- }
- else if (wc <= 0x7FF)
- {
- utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
- utf8_bytes[1] = 0x80 | (wc & 0x3F);
- utf8_bytes_filled = 2;
- }
- else if (wc <= 0xFFFF)
- {
- utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
- utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
- utf8_bytes[2] = 0x80 | (wc & 0x3F);
- utf8_bytes_filled = 3;
- }
- else if (wc <= 0x10FFFF)
- {
- utf8_bytes[0] = 0xF0 | ((wc >> 18 ) & 0x07);
- utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
- utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
- utf8_bytes[3] = 0x80 | (wc & 0x3F);
- utf8_bytes_filled = 4;
- }
- else
- {
- // unknown character
- utf8_bytes[0] = wc;
- utf8_bytes_filled = 1;
- }
+ assert(utf8_bytes_filled > 0);
+ assert(utf8_bytes_index == 0);
}
+
+ // use buffer
+ assert(utf8_bytes_filled > 0);
+ assert(utf8_bytes_index < utf8_bytes_filled);
+ return utf8_bytes[utf8_bytes_index++];
}
private:
+ template<size_t T>
+ void fill_buffer()
+ {
+ wide_string_input_helper<WideStringType, T>::fill_buffer(str, current_wchar, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
+ }
+
/// the wstring to process
const WideStringType& str;
@@ -2157,15 +2206,18 @@ class input_adapter
int>::type = 0>
input_adapter(IteratorType first, IteratorType last)
{
+#ifndef NDEBUG
// assertion to check that the iterator range is indeed contiguous,
// see http://stackoverflow.com/a/35008842/266378 for more discussion
- assert(std::accumulate(
- first, last, std::pair<bool, int>(true, 0),
- [&first](std::pair<bool, int> res, decltype(*first) val)
+ const auto is_contiguous = std::accumulate(
+ first, last, std::pair<bool, int>(true, 0),
+ [&first](std::pair<bool, int> res, decltype(*first) val)
{
res.first &= (val == *(std::next(std::addressof(*first), res.second++)));
return res;
- }).first);
+ }).first;
+ assert(is_contiguous);
+#endif
// assertion to check that each element is 1 byte long
static_assert(
@@ -3569,73 +3621,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...>
-using void_t = void;
-}
-}
-
-
-// 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>
@@ -10172,7 +10157,7 @@ class serializer
return;
}
- const bool is_negative = (x <= 0) and (x != 0); // see issue #755
+ const bool is_negative = not (x >= 0); // see issue #755
std::size_t i = 0;
while (x != 0)
@@ -11151,8 +11136,10 @@ struct adl_serializer
@param[in,out] val value to write to
*/
template<typename BasicJsonType, typename ValueType>
- static void from_json(BasicJsonType&& j, ValueType& val) noexcept(
- noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
+ static auto from_json(BasicJsonType&& j, ValueType& val) noexcept(
+ 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);
}
@@ -11166,9 +11153,11 @@ struct adl_serializer
@param[in,out] j JSON value to write to
@param[in] val value to read from
*/
- template<typename BasicJsonType, typename ValueType>
- static void to_json(BasicJsonType& j, ValueType&& val) noexcept(
+ template <typename BasicJsonType, typename ValueType>
+ static auto to_json(BasicJsonType& j, ValueType&& val) noexcept(
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));
}
@@ -12053,7 +12042,7 @@ class basic_json
object = nullptr; // silence warning, see #821
if (JSON_UNLIKELY(t == value_t::null))
{
- JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.2.0")); // LCOV_EXCL_LINE
+ JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.3.0")); // LCOV_EXCL_LINE
}
break;
}
@@ -12349,7 +12338,7 @@ class basic_json
template <typename CompatibleType,
typename U = detail::uncvref_t<CompatibleType>,
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(
JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
std::forward<CompatibleType>(val))))
@@ -13730,17 +13719,64 @@ class basic_json
}
/*!
- @brief get a pointer value (explicit)
+ @brief get a value (explicit)
- Explicit pointer access to the internally stored JSON value. No copies are
+ Explicit type conversion between the JSON value and a compatible value.
+ The value is filled into the input parameter by calling the @ref json_serializer<ValueType>
+ `from_json()` method.
+
+ The function is equivalent to executing
+ @code {.cpp}
+ ValueType v;
+ JSONSerializer<ValueType>::from_json(*this, v);
+ @endcode
+
+ This overloads is chosen if:
+ - @a ValueType is not @ref basic_json,
+ - @ref json_serializer<ValueType> has a `from_json()` method of the form
+ `void from_json(const basic_json&, ValueType&)`, and
+
+ @tparam ValueType the input parameter type.
+
+ @return the input parameter, allowing chaining calls.
+
+ @throw what @ref json_serializer<ValueType> `from_json()` method throws
+
+ @liveexample{The example below shows several conversions from JSON values
+ to other types. There a few things to note: (1) Floating-point numbers can
+ be converted to integers\, (2) A JSON array can be converted to a standard
+ `std::vector<short>`\, (3) A JSON object can be converted to C++
+ associative containers such as `std::unordered_map<std::string\,
+ json>`.,get_to}
+
+ @since version 3.3.0
+ */
+ template<typename ValueType,
+ detail::enable_if_t <
+ not detail::is_basic_json<ValueType>::value and
+ detail::has_from_json<basic_json_t, ValueType>::value,
+ int> = 0>
+ ValueType & get_to(ValueType& v) const noexcept(noexcept(
+ JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
+ {
+ JSONSerializer<ValueType>::from_json(*this, v);
+ return v;
+ }
+
+
+ /*!
+ @brief get a pointer value (implicit)
+
+ Implicit pointer access to the internally stored JSON value. No copies are
made.
- @warning The pointer becomes invalid if the underlying JSON object
- changes.
+ @warning Writing data to the pointee of the result yields an undefined
+ state.
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
- @ref number_unsigned_t, or @ref number_float_t.
+ @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
+ assertion.
@return pointer to the internally stored JSON value if the requested
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
@@ -13750,45 +13786,43 @@ class basic_json
@liveexample{The example below shows how pointers to internal values of a
JSON value can be requested. Note that no type conversions are made and a
`nullptr` is returned if the value and the requested pointer type does not
- match.,get__PointerType}
-
- @sa @ref get_ptr() for explicit pointer-member access
+ match.,get_ptr}
@since version 1.0.0
*/
template<typename PointerType, typename std::enable_if<
std::is_pointer<PointerType>::value, int>::type = 0>
- PointerType get() noexcept
+ auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
{
- // delegate the call to get_ptr
- return get_ptr<PointerType>();
+ // delegate the call to get_impl_ptr<>()
+ return get_impl_ptr(static_cast<PointerType>(nullptr));
}
/*!
- @brief get a pointer value (explicit)
- @copydoc get()
+ @brief get a pointer value (implicit)
+ @copydoc get_ptr()
*/
template<typename PointerType, typename std::enable_if<
- std::is_pointer<PointerType>::value, int>::type = 0>
- constexpr const PointerType get() const noexcept
+ std::is_pointer<PointerType>::value and
+ std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
+ constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
{
- // delegate the call to get_ptr
- return get_ptr<PointerType>();
+ // delegate the call to get_impl_ptr<>() const
+ return get_impl_ptr(static_cast<PointerType>(nullptr));
}
/*!
- @brief get a pointer value (implicit)
+ @brief get a pointer value (explicit)
- Implicit pointer access to the internally stored JSON value. No copies are
+ Explicit pointer access to the internally stored JSON value. No copies are
made.
- @warning Writing data to the pointee of the result yields an undefined
- state.
+ @warning The pointer becomes invalid if the underlying JSON object
+ changes.
@tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
- @ref number_unsigned_t, or @ref number_float_t. Enforced by a static
- assertion.
+ @ref number_unsigned_t, or @ref number_float_t.
@return pointer to the internally stored JSON value if the requested
pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
@@ -13798,59 +13832,30 @@ class basic_json
@liveexample{The example below shows how pointers to internal values of a
JSON value can be requested. Note that no type conversions are made and a
`nullptr` is returned if the value and the requested pointer type does not
- match.,get_ptr}
+ match.,get__PointerType}
+
+ @sa @ref get_ptr() for explicit pointer-member access
@since version 1.0.0
*/
template<typename PointerType, typename std::enable_if<
std::is_pointer<PointerType>::value, int>::type = 0>
- PointerType get_ptr() noexcept
+ auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
{
- // get the type of the PointerType (remove pointer and const)
- using pointee_t = typename std::remove_const<typename
- std::remove_pointer<typename
- std::remove_const<PointerType>::type>::type>::type;
- // make sure the type matches the allowed types
- static_assert(
- std::is_same<object_t, pointee_t>::value
- or std::is_same<array_t, pointee_t>::value
- or std::is_same<string_t, pointee_t>::value
- or std::is_same<boolean_t, pointee_t>::value
- or std::is_same<number_integer_t, pointee_t>::value
- or std::is_same<number_unsigned_t, pointee_t>::value
- or std::is_same<number_float_t, pointee_t>::value
- , "incompatible pointer type");
-
- // delegate the call to get_impl_ptr<>()
- return get_impl_ptr(static_cast<PointerType>(nullptr));
+ // delegate the call to get_ptr
+ return get_ptr<PointerType>();
}
/*!
- @brief get a pointer value (implicit)
- @copydoc get_ptr()
+ @brief get a pointer value (explicit)
+ @copydoc get()
*/
template<typename PointerType, typename std::enable_if<
- std::is_pointer<PointerType>::value and
- std::is_const<typename std::remove_pointer<PointerType>::type>::value, int>::type = 0>
- constexpr const PointerType get_ptr() const noexcept
+ std::is_pointer<PointerType>::value, int>::type = 0>
+ constexpr auto get() const noexcept -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
{
- // get the type of the PointerType (remove pointer and const)
- using pointee_t = typename std::remove_const<typename
- std::remove_pointer<typename
- std::remove_const<PointerType>::type>::type>::type;
- // make sure the type matches the allowed types
- static_assert(
- std::is_same<object_t, pointee_t>::value
- or std::is_same<array_t, pointee_t>::value
- or std::is_same<string_t, pointee_t>::value
- or std::is_same<boolean_t, pointee_t>::value
- or std::is_same<number_integer_t, pointee_t>::value
- or std::is_same<number_unsigned_t, pointee_t>::value
- or std::is_same<number_float_t, pointee_t>::value
- , "incompatible pointer type");
-
- // delegate the call to get_impl_ptr<>() const
- return get_impl_ptr(static_cast<PointerType>(nullptr));
+ // delegate the call to get_ptr
+ return get_ptr<PointerType>();
}
/*!
@@ -13934,12 +13939,14 @@ class basic_json
not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
not std::is_same<ValueType, typename string_t::value_type>::value and
not detail::is_basic_json<ValueType>::value
+
#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
and not std::is_same<ValueType, typename std::string_view>::value
#endif
#endif
+ and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
, int >::type = 0 >
operator ValueType() const
{
@@ -14203,7 +14210,7 @@ class basic_json
return m_value.array->operator[](idx);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
}
/*!
@@ -14233,7 +14240,7 @@ class basic_json
return m_value.array->operator[](idx);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name())));
}
/*!
@@ -14279,7 +14286,7 @@ class basic_json
return m_value.object->operator[](key);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
}
/*!
@@ -14321,7 +14328,7 @@ class basic_json
return m_value.object->find(key)->second;
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
}
/*!
@@ -14368,7 +14375,7 @@ class basic_json
return m_value.object->operator[](key);
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
}
/*!
@@ -14411,7 +14418,7 @@ class basic_json
return m_value.object->find(key)->second;
}
- JSON_THROW(type_error::create(305, "cannot use operator[] with " + std::string(type_name())));
+ JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name())));
}
/*!
@@ -16049,6 +16056,26 @@ class basic_json
return {it, res.second};
}
+ /// Helper for insertion of an iterator
+ /// @note: This uses std::distance to support GCC 4.8,
+ /// see https://github.com/nlohmann/json/pull/1257
+ template<typename... Args>
+ iterator insert_iterator(const_iterator pos, Args&& ... args)
+ {
+ iterator result(this);
+ assert(m_value.array != nullptr);
+
+ auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
+ m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
+ result.m_it.array_iterator = m_value.array->begin() + insert_pos;
+
+ // This could have been written as:
+ // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
+ // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
+
+ return result;
+ }
+
/*!
@brief inserts element
@@ -16083,9 +16110,7 @@ class basic_json
}
// insert to array and return iterator
- iterator result(this);
- result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, val);
- return result;
+ return insert_iterator(pos, val);
}
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
@@ -16136,9 +16161,7 @@ class basic_json
}
// insert to array and return iterator
- iterator result(this);
- result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
- return result;
+ return insert_iterator(pos, cnt, val);
}
JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name())));
@@ -16200,12 +16223,7 @@ class basic_json
}
// insert to array and return iterator
- iterator result(this);
- result.m_it.array_iterator = m_value.array->insert(
- pos.m_it.array_iterator,
- first.m_it.array_iterator,
- last.m_it.array_iterator);
- return result;
+ return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
}
/*!
@@ -16247,9 +16265,7 @@ class basic_json
}
// insert to array and return iterator
- iterator result(this);
- result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
- return result;
+ return insert_iterator(pos, ilist.begin(), ilist.end());
}
/*!
@@ -18797,19 +18813,6 @@ class basic_json
// specialization of std::swap, and std::hash
namespace std
{
-/*!
-@brief exchanges the values of two JSON objects
-
-@since version 1.0.0
-*/
-template<>
-inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
- is_nothrow_move_constructible<nlohmann::json>::value and
- is_nothrow_move_assignable<nlohmann::json>::value
-)
-{
- j1.swap(j2);
-}
/// hash value for JSON objects
template<>
@@ -18845,6 +18848,20 @@ struct less< ::nlohmann::detail::value_t>
}
};
+/*!
+@brief exchanges the values of two JSON objects
+
+@since version 1.0.0
+*/
+template<>
+inline void swap<nlohmann::json>(nlohmann::json& j1, nlohmann::json& j2) noexcept(
+ is_nothrow_move_constructible<nlohmann::json>::value and
+ is_nothrow_move_assignable<nlohmann::json>::value
+)
+{
+ j1.swap(j2);
+}
+
} // namespace std
/*!
@@ -18906,7 +18923,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