From a485aa8d272f3656c1fb5840ce100f3288f7e2da Mon Sep 17 00:00:00 2001
From: Niels <niels.lohmann@gmail.com>
Date: Tue, 30 Aug 2016 23:44:15 +0200
Subject: [PATCH] cleanup and improvement of branch coverage

---
 src/json.hpp                           | 218 ++++++++++---------------
 src/json.hpp.re2c                      | 218 ++++++++++---------------
 test/src/unit-class_const_iterator.cpp |  16 ++
 test/src/unit-deserialization.cpp      | 104 ++++++++----
 4 files changed, 265 insertions(+), 291 deletions(-)

diff --git a/src/json.hpp b/src/json.hpp
index d6f8925f..2f0f02d5 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -1164,11 +1164,10 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class CompatibleObjectType, typename
-              std::enable_if<
-                  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
-                  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
-              = 0>
+    template<class CompatibleObjectType, typename std::enable_if<
+                 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
+                 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
+             = 0>
     basic_json(const CompatibleObjectType& val)
         : m_type(value_t::object)
     {
@@ -1229,16 +1228,15 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class CompatibleArrayType, typename
-              std::enable_if<
-                  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
-                  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
-              = 0>
+    template<class CompatibleArrayType, typename std::enable_if<
+                 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
+                 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
+             = 0>
     basic_json(const CompatibleArrayType& val)
         : m_type(value_t::array)
     {
@@ -1324,10 +1322,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class CompatibleStringType, typename
-              std::enable_if<
-                  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
-              = 0>
+    template<class CompatibleStringType, typename std::enable_if<
+                 std::is_constructible<string_t, CompatibleStringType>::value, int>::type
+             = 0>
     basic_json(const CompatibleStringType& val)
         : basic_json(string_t(val))
     {
@@ -1377,8 +1374,7 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename T,
-             typename std::enable_if<
+    template<typename T, typename std::enable_if<
                  not (std::is_same<T, int>::value)
                  and std::is_same<T, number_integer_t>::value
                  , int>::type
@@ -1477,8 +1473,7 @@ class basic_json
 
     @since version 2.0.0
     */
-    template<typename T,
-             typename std::enable_if<
+    template<typename T, typename std::enable_if<
                  not (std::is_same<T, int>::value)
                  and std::is_same<T, number_unsigned_t>::value
                  , int>::type
@@ -1509,13 +1504,11 @@ class basic_json
 
     @since version 2.0.0
     */
-    template <typename CompatibleNumberUnsignedType, typename
-              std::enable_if <
-                  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
-                  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
-                  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
-                  CompatibleNumberUnsignedType>::type
-              = 0>
+    template<typename CompatibleNumberUnsignedType, typename std::enable_if<
+                 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
+                 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
+                 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, CompatibleNumberUnsignedType>::type
+             = 0>
     basic_json(const CompatibleNumberUnsignedType val) noexcept
         : m_type(value_t::number_unsigned),
           m_value(static_cast<number_unsigned_t>(val))
@@ -1591,11 +1584,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename CompatibleNumberFloatType, typename = typename
-             std::enable_if<
+    template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
                  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
-                 std::is_floating_point<CompatibleNumberFloatType>::value>::type
-             >
+                 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
     basic_json(const CompatibleNumberFloatType val) noexcept
         : basic_json(number_float_t(val))
     {
@@ -1672,8 +1663,8 @@ class basic_json
     @since version 1.0.0
     */
     basic_json(std::initializer_list<basic_json> init,
-               bool type_deduction = true,
-               value_t manual_type = value_t::array)
+               const bool type_deduction = true,
+               const value_t manual_type = value_t::array)
     {
         // check if each element is an array with two elements whose first
         // element is a string
@@ -1862,12 +1853,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class InputIT, typename
-              std::enable_if<
-                  std::is_same<InputIT, typename basic_json_t::iterator>::value or
-                  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
-                  , int>::type
-              = 0>
+    template<class InputIT, typename = typename std::enable_if<
+                 std::is_same<InputIT, typename basic_json_t::iterator>::value or
+                 std::is_same<InputIT, typename basic_json_t::const_iterator>::value>::type>
     basic_json(InputIT first, InputIT last)
     {
         assert(first.m_object != nullptr);
@@ -2616,11 +2604,10 @@ class basic_json
     //////////////////
 
     /// get an object (explicit)
-    template <class T, typename
-              std::enable_if<
-                  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
-                  std::is_convertible<basic_json_t, typename T::mapped_type>::value
-                  , int>::type = 0>
+    template<class T, typename std::enable_if<
+                 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
+                 std::is_convertible<basic_json_t, typename T::mapped_type>::value
+                 , int>::type = 0>
     T get_impl(T*) const
     {
         if (is_object())
@@ -2647,14 +2634,13 @@ class basic_json
     }
 
     /// get an array (explicit)
-    template <class T, typename
-              std::enable_if<
-                  std::is_convertible<basic_json_t, typename T::value_type>::value and
-                  not std::is_same<basic_json_t, typename T::value_type>::value and
-                  not std::is_arithmetic<T>::value and
-                  not std::is_convertible<std::string, T>::value and
-                  not has_mapped_type<T>::value
-                  , int>::type = 0>
+    template<class T, typename std::enable_if<
+                 std::is_convertible<basic_json_t, typename T::value_type>::value and
+                 not std::is_same<basic_json_t, typename T::value_type>::value and
+                 not std::is_arithmetic<T>::value and
+                 not std::is_convertible<std::string, T>::value and
+                 not has_mapped_type<T>::value
+                 , int>::type = 0>
     T get_impl(T*) const
     {
         if (is_array())
@@ -2674,11 +2660,10 @@ class basic_json
     }
 
     /// get an array (explicit)
-    template <class T, typename
-              std::enable_if<
-                  std::is_convertible<basic_json_t, T>::value and
-                  not std::is_same<basic_json_t, T>::value
-                  , int>::type = 0>
+    template<class T, typename std::enable_if<
+                 std::is_convertible<basic_json_t, T>::value and
+                 not std::is_same<basic_json_t, T>::value
+                 , int>::type = 0>
     std::vector<T> get_impl(std::vector<T>*) const
     {
         if (is_array())
@@ -2699,11 +2684,10 @@ class basic_json
     }
 
     /// get an array (explicit)
-    template <class T, typename
-              std::enable_if<
-                  std::is_same<basic_json, typename T::value_type>::value and
-                  not has_mapped_type<T>::value
-                  , int>::type = 0>
+    template<class T, typename std::enable_if<
+                 std::is_same<basic_json, typename T::value_type>::value and
+                 not has_mapped_type<T>::value
+                 , int>::type = 0>
     T get_impl(T*) const
     {
         if (is_array())
@@ -2730,10 +2714,9 @@ class basic_json
     }
 
     /// get a string (explicit)
-    template <typename T, typename
-              std::enable_if<
-                  std::is_convertible<string_t, T>::value
-                  , int>::type = 0>
+    template<typename T, typename std::enable_if<
+                 std::is_convertible<string_t, T>::value
+                 , int>::type = 0>
     T get_impl(T*) const
     {
         if (is_string())
@@ -2747,10 +2730,8 @@ class basic_json
     }
 
     /// get a number (explicit)
-    template<typename T, typename
-             std::enable_if<
-                 std::is_arithmetic<T>::value
-                 , int>::type = 0>
+    template<typename T, typename std::enable_if<
+                 std::is_arithmetic<T>::value, int>::type = 0>
     T get_impl(T*) const
     {
         switch (m_type)
@@ -2939,10 +2920,8 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename ValueType, typename
-             std::enable_if<
-                 not std::is_pointer<ValueType>::value
-                 , int>::type = 0>
+    template<typename ValueType, typename = typename std::enable_if<
+                 not std::is_pointer<ValueType>::value>::type>
     ValueType get() const
     {
         return get_impl(static_cast<ValueType*>(nullptr));
@@ -2975,10 +2954,8 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename PointerType, typename
-             std::enable_if<
-                 std::is_pointer<PointerType>::value
-                 , int>::type = 0>
+    template<typename PointerType, typename = typename std::enable_if<
+                 std::is_pointer<PointerType>::value>::type>
     PointerType get() noexcept
     {
         // delegate the call to get_ptr
@@ -2989,10 +2966,8 @@ class basic_json
     @brief get a pointer value (explicit)
     @copydoc get()
     */
-    template<typename PointerType, typename
-             std::enable_if<
-                 std::is_pointer<PointerType>::value
-                 , int>::type = 0>
+    template<typename PointerType, typename = typename std::enable_if<
+                 std::is_pointer<PointerType>::value>::type>
     constexpr const PointerType get() const noexcept
     {
         // delegate the call to get_ptr
@@ -3025,10 +3000,8 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename PointerType, typename
-             std::enable_if<
-                 std::is_pointer<PointerType>::value
-                 , int>::type = 0>
+    template<typename PointerType, typename = typename std::enable_if<
+                 std::is_pointer<PointerType>::value>::type>
     PointerType get_ptr() noexcept
     {
         // get the type of the PointerType (remove pointer and const)
@@ -3054,11 +3027,9 @@ class basic_json
     @brief get a pointer value (implicit)
     @copydoc get_ptr()
     */
-    template<typename PointerType, typename
-             std::enable_if<
+    template<typename PointerType, typename = typename std::enable_if<
                  std::is_pointer<PointerType>::value
-                 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
-                 , int>::type = 0>
+                 and std::is_const<typename std::remove_pointer<PointerType>::type>::value>::type>
     constexpr const PointerType get_ptr() const noexcept
     {
         // get the type of the PointerType (remove pointer and const)
@@ -3106,10 +3077,8 @@ class basic_json
 
     @since version 1.1.0
     */
-    template<typename ReferenceType, typename
-             std::enable_if<
-                 std::is_reference<ReferenceType>::value
-                 , int>::type = 0>
+    template<typename ReferenceType, typename = typename std::enable_if<
+                 std::is_reference<ReferenceType>::value>::type>
     ReferenceType get_ref()
     {
         // delegate call to get_ref_impl
@@ -3120,11 +3089,9 @@ class basic_json
     @brief get a reference value (implicit)
     @copydoc get_ref()
     */
-    template<typename ReferenceType, typename
-             std::enable_if<
+    template<typename ReferenceType, typename = typename std::enable_if<
                  std::is_reference<ReferenceType>::value
-                 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
-                 , int>::type = 0>
+                 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value>::type>
     ReferenceType get_ref() const
     {
         // delegate call to get_ref_impl
@@ -3159,14 +3126,13 @@ class basic_json
 
     @since version 1.0.0
     */
-    template < typename ValueType, typename
-               std::enable_if <
+    template < typename ValueType, typename = typename std::enable_if <
                    not std::is_pointer<ValueType>::value
                    and not std::is_same<ValueType, typename string_t::value_type>::value
 #ifndef _MSC_VER  // Fix for issue #167 operator<< abiguity under VS2015
                    and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
 #endif
-                   , int >::type = 0 >
+                   >::type >
     operator ValueType() const
     {
         // delegate the call to get<>() const
@@ -3752,10 +3718,8 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class ValueType, typename
-              std::enable_if<
-                  std::is_convertible<basic_json_t, ValueType>::value
-                  , int>::type = 0>
+    template<class ValueType, typename = typename std::enable_if<
+                 std::is_convertible<basic_json_t, ValueType>::value>::type>
     ValueType value(const typename object_t::key_type& key, ValueType default_value) const
     {
         // at only works for objects
@@ -3828,10 +3792,8 @@ class basic_json
 
     @since version 2.0.2
     */
-    template <class ValueType, typename
-              std::enable_if<
-                  std::is_convertible<basic_json_t, ValueType>::value
-                  , int>::type = 0>
+    template<class ValueType, typename = typename std::enable_if<
+                 std::is_convertible<basic_json_t, ValueType>::value>::type>
     ValueType value(const json_pointer& ptr, ValueType default_value) const
     {
         // at only works for objects
@@ -3992,12 +3954,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class InteratorType, typename
-              std::enable_if<
-                  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
-                  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
-                  , int>::type
-              = 0>
+    template<class InteratorType, typename = typename std::enable_if<
+                 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
+                 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value>::type>
     InteratorType erase(InteratorType pos)
     {
         // make sure iterator fits the current value
@@ -4101,12 +4060,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class InteratorType, typename
-              std::enable_if<
-                  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
-                  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
-                  , int>::type
-              = 0>
+    template<class InteratorType, typename = typename std::enable_if<
+                 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
+                 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value>::type>
     InteratorType erase(InteratorType first, InteratorType last)
     {
         // make sure iterator fits the current value
@@ -6267,7 +6223,7 @@ class basic_json
               const unsigned int current_indent = 0) const
     {
         // variable to hold indentation for recursive calls
-        unsigned int new_indent = current_indent;
+        auto new_indent = current_indent;
 
         switch (m_type)
         {
@@ -7561,7 +7517,7 @@ class basic_json
                                    const std::size_t codepoint2 = 0)
         {
             // calculate the code point from the given code points
-            std::size_t codepoint = codepoint1;
+            auto codepoint = codepoint1;
 
             // check if codepoint1 is a high surrogate
             if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
@@ -9524,7 +9480,7 @@ basic_json_parser_63:
                 auto reference_token = reference_string.substr(start, slash - start);
 
                 // check reference tokens are properly escaped
-                for (size_t pos = reference_token.find_first_of("~");
+                for (auto pos = reference_token.find_first_of("~");
                         pos != std::string::npos;
                         pos = reference_token.find_first_of("~", pos + 1))
                 {
@@ -9569,7 +9525,7 @@ basic_json_parser_63:
             assert(not f.empty());
 
             for (
-                size_t pos = s.find(f);         // find first occurrence of f
+                auto pos = s.find(f);         // find first occurrence of f
                 pos != std::string::npos;       // make sure f was found
                 s.replace(pos, f.size(), t),    // replace with t
                 pos = s.find(f, pos + t.size()) // find next occurrence of f
@@ -9969,7 +9925,7 @@ basic_json_parser_63:
             else
             {
                 // make sure the top element of the pointer exists
-                json_pointer top_pointer = ptr.top();
+                auto top_pointer = ptr.top();
                 if (top_pointer != ptr)
                 {
                     basic_json& x = result.at(top_pointer);
@@ -10377,7 +10333,7 @@ namespace std
 
 @since version 1.0.0
 */
-template <>
+template<>
 inline void swap(nlohmann::json& j1,
                  nlohmann::json& j2) noexcept(
                      is_nothrow_move_constructible<nlohmann::json>::value and
@@ -10388,7 +10344,7 @@ inline void swap(nlohmann::json& j1,
 }
 
 /// hash value for JSON objects
-template <>
+template<>
 struct hash<nlohmann::json>
 {
     /*!
diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c
index 75fc27e5..28532a8d 100644
--- a/src/json.hpp.re2c
+++ b/src/json.hpp.re2c
@@ -1164,11 +1164,10 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class CompatibleObjectType, typename
-              std::enable_if<
-                  std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
-                  std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
-              = 0>
+    template<class CompatibleObjectType, typename std::enable_if<
+                 std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
+                 std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
+             = 0>
     basic_json(const CompatibleObjectType& val)
         : m_type(value_t::object)
     {
@@ -1229,16 +1228,15 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class CompatibleArrayType, typename
-              std::enable_if<
-                  not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
-                  not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
-                  std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
-              = 0>
+    template<class CompatibleArrayType, typename std::enable_if<
+                 not std::is_same<CompatibleArrayType, typename basic_json_t::iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename basic_json_t::const_iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename basic_json_t::reverse_iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename basic_json_t::const_reverse_iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename array_t::iterator>::value and
+                 not std::is_same<CompatibleArrayType, typename array_t::const_iterator>::value and
+                 std::is_constructible<basic_json, typename CompatibleArrayType::value_type>::value, int>::type
+             = 0>
     basic_json(const CompatibleArrayType& val)
         : m_type(value_t::array)
     {
@@ -1324,10 +1322,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class CompatibleStringType, typename
-              std::enable_if<
-                  std::is_constructible<string_t, CompatibleStringType>::value, int>::type
-              = 0>
+    template<class CompatibleStringType, typename std::enable_if<
+                 std::is_constructible<string_t, CompatibleStringType>::value, int>::type
+             = 0>
     basic_json(const CompatibleStringType& val)
         : basic_json(string_t(val))
     {
@@ -1377,8 +1374,7 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename T,
-             typename std::enable_if<
+    template<typename T, typename std::enable_if<
                  not (std::is_same<T, int>::value)
                  and std::is_same<T, number_integer_t>::value
                  , int>::type
@@ -1477,8 +1473,7 @@ class basic_json
 
     @since version 2.0.0
     */
-    template<typename T,
-             typename std::enable_if<
+    template<typename T, typename std::enable_if<
                  not (std::is_same<T, int>::value)
                  and std::is_same<T, number_unsigned_t>::value
                  , int>::type
@@ -1509,13 +1504,11 @@ class basic_json
 
     @since version 2.0.0
     */
-    template <typename CompatibleNumberUnsignedType, typename
-              std::enable_if <
-                  std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
-                  std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
-                  not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed,
-                  CompatibleNumberUnsignedType>::type
-              = 0>
+    template<typename CompatibleNumberUnsignedType, typename std::enable_if<
+                 std::is_constructible<number_unsigned_t, CompatibleNumberUnsignedType>::value and
+                 std::numeric_limits<CompatibleNumberUnsignedType>::is_integer and
+                 not std::numeric_limits<CompatibleNumberUnsignedType>::is_signed, CompatibleNumberUnsignedType>::type
+             = 0>
     basic_json(const CompatibleNumberUnsignedType val) noexcept
         : m_type(value_t::number_unsigned),
           m_value(static_cast<number_unsigned_t>(val))
@@ -1591,11 +1584,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename CompatibleNumberFloatType, typename = typename
-             std::enable_if<
+    template<typename CompatibleNumberFloatType, typename = typename std::enable_if<
                  std::is_constructible<number_float_t, CompatibleNumberFloatType>::value and
-                 std::is_floating_point<CompatibleNumberFloatType>::value>::type
-             >
+                 std::is_floating_point<CompatibleNumberFloatType>::value>::type>
     basic_json(const CompatibleNumberFloatType val) noexcept
         : basic_json(number_float_t(val))
     {
@@ -1672,8 +1663,8 @@ class basic_json
     @since version 1.0.0
     */
     basic_json(std::initializer_list<basic_json> init,
-               bool type_deduction = true,
-               value_t manual_type = value_t::array)
+               const bool type_deduction = true,
+               const value_t manual_type = value_t::array)
     {
         // check if each element is an array with two elements whose first
         // element is a string
@@ -1862,12 +1853,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class InputIT, typename
-              std::enable_if<
-                  std::is_same<InputIT, typename basic_json_t::iterator>::value or
-                  std::is_same<InputIT, typename basic_json_t::const_iterator>::value
-                  , int>::type
-              = 0>
+    template<class InputIT, typename = typename std::enable_if<
+                 std::is_same<InputIT, typename basic_json_t::iterator>::value or
+                 std::is_same<InputIT, typename basic_json_t::const_iterator>::value>::type>
     basic_json(InputIT first, InputIT last)
     {
         assert(first.m_object != nullptr);
@@ -2616,11 +2604,10 @@ class basic_json
     //////////////////
 
     /// get an object (explicit)
-    template <class T, typename
-              std::enable_if<
-                  std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
-                  std::is_convertible<basic_json_t, typename T::mapped_type>::value
-                  , int>::type = 0>
+    template<class T, typename std::enable_if<
+                 std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
+                 std::is_convertible<basic_json_t, typename T::mapped_type>::value
+                 , int>::type = 0>
     T get_impl(T*) const
     {
         if (is_object())
@@ -2647,14 +2634,13 @@ class basic_json
     }
 
     /// get an array (explicit)
-    template <class T, typename
-              std::enable_if<
-                  std::is_convertible<basic_json_t, typename T::value_type>::value and
-                  not std::is_same<basic_json_t, typename T::value_type>::value and
-                  not std::is_arithmetic<T>::value and
-                  not std::is_convertible<std::string, T>::value and
-                  not has_mapped_type<T>::value
-                  , int>::type = 0>
+    template<class T, typename std::enable_if<
+                 std::is_convertible<basic_json_t, typename T::value_type>::value and
+                 not std::is_same<basic_json_t, typename T::value_type>::value and
+                 not std::is_arithmetic<T>::value and
+                 not std::is_convertible<std::string, T>::value and
+                 not has_mapped_type<T>::value
+                 , int>::type = 0>
     T get_impl(T*) const
     {
         if (is_array())
@@ -2674,11 +2660,10 @@ class basic_json
     }
 
     /// get an array (explicit)
-    template <class T, typename
-              std::enable_if<
-                  std::is_convertible<basic_json_t, T>::value and
-                  not std::is_same<basic_json_t, T>::value
-                  , int>::type = 0>
+    template<class T, typename std::enable_if<
+                 std::is_convertible<basic_json_t, T>::value and
+                 not std::is_same<basic_json_t, T>::value
+                 , int>::type = 0>
     std::vector<T> get_impl(std::vector<T>*) const
     {
         if (is_array())
@@ -2699,11 +2684,10 @@ class basic_json
     }
 
     /// get an array (explicit)
-    template <class T, typename
-              std::enable_if<
-                  std::is_same<basic_json, typename T::value_type>::value and
-                  not has_mapped_type<T>::value
-                  , int>::type = 0>
+    template<class T, typename std::enable_if<
+                 std::is_same<basic_json, typename T::value_type>::value and
+                 not has_mapped_type<T>::value
+                 , int>::type = 0>
     T get_impl(T*) const
     {
         if (is_array())
@@ -2730,10 +2714,9 @@ class basic_json
     }
 
     /// get a string (explicit)
-    template <typename T, typename
-              std::enable_if<
-                  std::is_convertible<string_t, T>::value
-                  , int>::type = 0>
+    template<typename T, typename std::enable_if<
+                 std::is_convertible<string_t, T>::value
+                 , int>::type = 0>
     T get_impl(T*) const
     {
         if (is_string())
@@ -2747,10 +2730,8 @@ class basic_json
     }
 
     /// get a number (explicit)
-    template<typename T, typename
-             std::enable_if<
-                 std::is_arithmetic<T>::value
-                 , int>::type = 0>
+    template<typename T, typename std::enable_if<
+                 std::is_arithmetic<T>::value, int>::type = 0>
     T get_impl(T*) const
     {
         switch (m_type)
@@ -2939,10 +2920,8 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename ValueType, typename
-             std::enable_if<
-                 not std::is_pointer<ValueType>::value
-                 , int>::type = 0>
+    template<typename ValueType, typename = typename std::enable_if<
+                 not std::is_pointer<ValueType>::value>::type>
     ValueType get() const
     {
         return get_impl(static_cast<ValueType*>(nullptr));
@@ -2975,10 +2954,8 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename PointerType, typename
-             std::enable_if<
-                 std::is_pointer<PointerType>::value
-                 , int>::type = 0>
+    template<typename PointerType, typename = typename std::enable_if<
+                 std::is_pointer<PointerType>::value>::type>
     PointerType get() noexcept
     {
         // delegate the call to get_ptr
@@ -2989,10 +2966,8 @@ class basic_json
     @brief get a pointer value (explicit)
     @copydoc get()
     */
-    template<typename PointerType, typename
-             std::enable_if<
-                 std::is_pointer<PointerType>::value
-                 , int>::type = 0>
+    template<typename PointerType, typename = typename std::enable_if<
+                 std::is_pointer<PointerType>::value>::type>
     constexpr const PointerType get() const noexcept
     {
         // delegate the call to get_ptr
@@ -3025,10 +3000,8 @@ class basic_json
 
     @since version 1.0.0
     */
-    template<typename PointerType, typename
-             std::enable_if<
-                 std::is_pointer<PointerType>::value
-                 , int>::type = 0>
+    template<typename PointerType, typename = typename std::enable_if<
+                 std::is_pointer<PointerType>::value>::type>
     PointerType get_ptr() noexcept
     {
         // get the type of the PointerType (remove pointer and const)
@@ -3054,11 +3027,9 @@ class basic_json
     @brief get a pointer value (implicit)
     @copydoc get_ptr()
     */
-    template<typename PointerType, typename
-             std::enable_if<
+    template<typename PointerType, typename = typename std::enable_if<
                  std::is_pointer<PointerType>::value
-                 and std::is_const<typename std::remove_pointer<PointerType>::type>::value
-                 , int>::type = 0>
+                 and std::is_const<typename std::remove_pointer<PointerType>::type>::value>::type>
     constexpr const PointerType get_ptr() const noexcept
     {
         // get the type of the PointerType (remove pointer and const)
@@ -3106,10 +3077,8 @@ class basic_json
 
     @since version 1.1.0
     */
-    template<typename ReferenceType, typename
-             std::enable_if<
-                 std::is_reference<ReferenceType>::value
-                 , int>::type = 0>
+    template<typename ReferenceType, typename = typename std::enable_if<
+                 std::is_reference<ReferenceType>::value>::type>
     ReferenceType get_ref()
     {
         // delegate call to get_ref_impl
@@ -3120,11 +3089,9 @@ class basic_json
     @brief get a reference value (implicit)
     @copydoc get_ref()
     */
-    template<typename ReferenceType, typename
-             std::enable_if<
+    template<typename ReferenceType, typename = typename std::enable_if<
                  std::is_reference<ReferenceType>::value
-                 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value
-                 , int>::type = 0>
+                 and std::is_const<typename std::remove_reference<ReferenceType>::type>::value>::type>
     ReferenceType get_ref() const
     {
         // delegate call to get_ref_impl
@@ -3159,14 +3126,13 @@ class basic_json
 
     @since version 1.0.0
     */
-    template < typename ValueType, typename
-               std::enable_if <
+    template < typename ValueType, typename = typename std::enable_if <
                    not std::is_pointer<ValueType>::value
                    and not std::is_same<ValueType, typename string_t::value_type>::value
 #ifndef _MSC_VER  // Fix for issue #167 operator<< abiguity under VS2015
                    and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
 #endif
-                   , int >::type = 0 >
+                   >::type >
     operator ValueType() const
     {
         // delegate the call to get<>() const
@@ -3752,10 +3718,8 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class ValueType, typename
-              std::enable_if<
-                  std::is_convertible<basic_json_t, ValueType>::value
-                  , int>::type = 0>
+    template<class ValueType, typename = typename std::enable_if<
+                 std::is_convertible<basic_json_t, ValueType>::value>::type>
     ValueType value(const typename object_t::key_type& key, ValueType default_value) const
     {
         // at only works for objects
@@ -3828,10 +3792,8 @@ class basic_json
 
     @since version 2.0.2
     */
-    template <class ValueType, typename
-              std::enable_if<
-                  std::is_convertible<basic_json_t, ValueType>::value
-                  , int>::type = 0>
+    template<class ValueType, typename = typename std::enable_if<
+                 std::is_convertible<basic_json_t, ValueType>::value>::type>
     ValueType value(const json_pointer& ptr, ValueType default_value) const
     {
         // at only works for objects
@@ -3992,12 +3954,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class InteratorType, typename
-              std::enable_if<
-                  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
-                  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
-                  , int>::type
-              = 0>
+    template<class InteratorType, typename = typename std::enable_if<
+                 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
+                 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value>::type>
     InteratorType erase(InteratorType pos)
     {
         // make sure iterator fits the current value
@@ -4101,12 +4060,9 @@ class basic_json
 
     @since version 1.0.0
     */
-    template <class InteratorType, typename
-              std::enable_if<
-                  std::is_same<InteratorType, typename basic_json_t::iterator>::value or
-                  std::is_same<InteratorType, typename basic_json_t::const_iterator>::value
-                  , int>::type
-              = 0>
+    template<class InteratorType, typename = typename std::enable_if<
+                 std::is_same<InteratorType, typename basic_json_t::iterator>::value or
+                 std::is_same<InteratorType, typename basic_json_t::const_iterator>::value>::type>
     InteratorType erase(InteratorType first, InteratorType last)
     {
         // make sure iterator fits the current value
@@ -6267,7 +6223,7 @@ class basic_json
               const unsigned int current_indent = 0) const
     {
         // variable to hold indentation for recursive calls
-        unsigned int new_indent = current_indent;
+        auto new_indent = current_indent;
 
         switch (m_type)
         {
@@ -7561,7 +7517,7 @@ class basic_json
                                    const std::size_t codepoint2 = 0)
         {
             // calculate the code point from the given code points
-            std::size_t codepoint = codepoint1;
+            auto codepoint = codepoint1;
 
             // check if codepoint1 is a high surrogate
             if (codepoint1 >= 0xD800 and codepoint1 <= 0xDBFF)
@@ -8821,7 +8777,7 @@ class basic_json
                 auto reference_token = reference_string.substr(start, slash - start);
 
                 // check reference tokens are properly escaped
-                for (size_t pos = reference_token.find_first_of("~");
+                for (auto pos = reference_token.find_first_of("~");
                         pos != std::string::npos;
                         pos = reference_token.find_first_of("~", pos + 1))
                 {
@@ -8866,7 +8822,7 @@ class basic_json
             assert(not f.empty());
 
             for (
-                size_t pos = s.find(f);         // find first occurrence of f
+                auto pos = s.find(f);         // find first occurrence of f
                 pos != std::string::npos;       // make sure f was found
                 s.replace(pos, f.size(), t),    // replace with t
                 pos = s.find(f, pos + t.size()) // find next occurrence of f
@@ -9266,7 +9222,7 @@ class basic_json
             else
             {
                 // make sure the top element of the pointer exists
-                json_pointer top_pointer = ptr.top();
+                auto top_pointer = ptr.top();
                 if (top_pointer != ptr)
                 {
                     basic_json& x = result.at(top_pointer);
@@ -9674,7 +9630,7 @@ namespace std
 
 @since version 1.0.0
 */
-template <>
+template<>
 inline void swap(nlohmann::json& j1,
                  nlohmann::json& j2) noexcept(
                      is_nothrow_move_constructible<nlohmann::json>::value and
@@ -9685,7 +9641,7 @@ inline void swap(nlohmann::json& j1,
 }
 
 /// hash value for JSON objects
-template <>
+template<>
 struct hash<nlohmann::json>
 {
     /*!
diff --git a/test/src/unit-class_const_iterator.cpp b/test/src/unit-class_const_iterator.cpp
index 4908b5ce..b64e7e3c 100644
--- a/test/src/unit-class_const_iterator.cpp
+++ b/test/src/unit-class_const_iterator.cpp
@@ -64,6 +64,22 @@ TEST_CASE("const_iterator class")
             json::const_iterator it2(&j);
             it2 = it;
         }
+
+        SECTION("copy constructor from non-const iterator")
+        {
+            SECTION("create from uninitialized iterator")
+            {
+                const json::iterator it {};
+                json::const_iterator cit(it);
+            }
+
+            SECTION("create from initialized iterator")
+            {
+                json j;
+                const json::iterator it = j.begin();
+                json::const_iterator cit(it);
+            }
+        }
     }
 
     SECTION("initialization")
diff --git a/test/src/unit-deserialization.cpp b/test/src/unit-deserialization.cpp
index 78188574..9d4c064f 100644
--- a/test/src/unit-deserialization.cpp
+++ b/test/src/unit-deserialization.cpp
@@ -33,41 +33,87 @@ using nlohmann::json;
 
 TEST_CASE("deserialization")
 {
-    SECTION("stream")
+    SECTION("successful deserialization")
     {
-        std::stringstream ss;
-        ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
-        json j = json::parse(ss);
-        CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+        SECTION("stream")
+        {
+            std::stringstream ss;
+            ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
+            json j = json::parse(ss);
+            CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+        }
+
+        SECTION("string")
+        {
+            json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}]";
+            json j = json::parse(s);
+            CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+        }
+
+        SECTION("operator<<")
+        {
+            std::stringstream ss;
+            ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
+            json j;
+            j << ss;
+            CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+        }
+
+        SECTION("operator>>")
+        {
+            std::stringstream ss;
+            ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
+            json j;
+            ss >> j;
+            CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+        }
+
+        SECTION("user-defined string literal")
+        {
+            CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+        }
     }
 
-    SECTION("string")
+    SECTION("successful deserialization")
     {
-        auto s = "[\"foo\",1,2,3,false,{\"one\":1}]";
-        json j = json::parse(s);
-        CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
-    }
+        SECTION("stream")
+        {
+            std::stringstream ss;
+            ss << "[\"foo\",1,2,3,false,{\"one\":1}";
+            CHECK_THROWS_AS(json::parse(ss), std::invalid_argument);
+            CHECK_THROWS_WITH(json::parse(ss), "parse error - unexpected end of input");
+        }
 
-    SECTION("operator<<")
-    {
-        std::stringstream ss;
-        ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
-        json j;
-        j << ss;
-        CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
-    }
+        SECTION("string")
+        {
+            json::string_t s = "[\"foo\",1,2,3,false,{\"one\":1}";
+            CHECK_THROWS_AS(json::parse(s), std::invalid_argument);
+            CHECK_THROWS_WITH(json::parse(s), "parse error - unexpected end of input; expected ']'");
+        }
 
-    SECTION("operator>>")
-    {
-        std::stringstream ss;
-        ss << "[\"foo\",1,2,3,false,{\"one\":1}]";
-        json j;
-        ss >> j;
-        CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
-    }
+        SECTION("operator<<")
+        {
+            std::stringstream ss;
+            ss << "[\"foo\",1,2,3,false,{\"one\":1}";
+            json j;
+            CHECK_THROWS_AS(j << ss, std::invalid_argument);
+            CHECK_THROWS_WITH(j << ss, "parse error - unexpected end of input");
+        }
 
-    SECTION("user-defined string literal")
-    {
-        CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
+        SECTION("operator>>")
+        {
+            std::stringstream ss;
+            ss << "[\"foo\",1,2,3,false,{\"one\":1}";
+            json j;
+            CHECK_THROWS_AS(ss >> j, std::invalid_argument);
+            CHECK_THROWS_WITH(ss >> j, "parse error - unexpected end of input");
+        }
+
+        SECTION("user-defined string literal")
+        {
+            CHECK_THROWS_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, std::invalid_argument);
+            CHECK_THROWS_WITH("[\"foo\",1,2,3,false,{\"one\":1}"_json,
+                              "parse error - unexpected end of input; expected ']'");
+        }
     }
 }