From 1eafac722016a8cacc2a657dcbd303b6f51ac074 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Th=C3=A9o=20DELRIEU?= <delrieutheo@gmail.com>
Date: Sun, 4 Dec 2016 17:52:55 +0100
Subject: [PATCH] remove explicit keyword on udt-constructor

---
 src/json.hpp          | 90 ++++++++++++++++++++++---------------------
 test/src/unit-udt.cpp | 18 ++++-----
 2 files changed, 55 insertions(+), 53 deletions(-)

diff --git a/src/json.hpp b/src/json.hpp
index fc7781ea..310779ea 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -257,30 +257,6 @@ struct is_compatible_integer_type_impl<true, RealIntegerType, CompatibleNumberIn
       RealLimits::is_signed == CompatibleLimits::is_signed;
 };
 
-// quickfix, just trying to make things compile before refactoring
-template <bool B, typename RealIntegerType, typename CompatibleEnumType>
-struct is_compatible_enum_type_impl : std::false_type{};
-
-template <typename RealIntegerType, typename CompatibleEnumType>
-struct is_compatible_enum_type_impl<true, RealIntegerType, CompatibleEnumType>
-{
-  using RealLimits = std::numeric_limits<RealIntegerType>;
-  using CompatibleLimits = std::numeric_limits<typename std::underlying_type<CompatibleEnumType>::type>;
-
-  static constexpr auto value =
-      CompatibleLimits::is_integer and
-      RealLimits::is_signed == CompatibleLimits::is_signed;
-};
-
-template <typename RealIntegerType, typename CompatibleEnumType>
-struct is_compatible_enum_type
-{
-  static constexpr auto value = is_compatible_enum_type_impl<
-// quickfix for all enums
-      std::is_enum<CompatibleEnumType>::value, RealIntegerType,
-      CompatibleEnumType>::value;
-};
-
 template <typename RealIntegerType, typename CompatibleNumberIntegerType>
 struct is_compatible_integer_type
 {
@@ -289,6 +265,27 @@ struct is_compatible_integer_type
       CompatibleNumberIntegerType>::value;
 };
 
+// quickfix, just trying to make things compile before refactoring
+template <bool B, typename RealIntegerType, typename CompatibleEnumType>
+struct is_compatible_enum_type_impl : std::false_type {};
+
+template <typename RealIntegerType, typename CompatibleEnumType>
+struct is_compatible_enum_type_impl<true, RealIntegerType, CompatibleEnumType>
+{
+  using Underlying = typename std::underlying_type<CompatibleEnumType>::type;
+  static constexpr auto value =
+      is_compatible_integer_type<RealIntegerType, Underlying>::value;
+};
+
+template <typename RealIntegerType, typename CompatibleEnumType>
+struct is_compatible_enum_type
+{
+  static constexpr auto value =
+      is_compatible_enum_type_impl<std::is_enum<CompatibleEnumType>::value,
+                                   RealIntegerType,
+                                   CompatibleEnumType>::value;
+};
+
 template <typename RealFloat, typename CompatibleFloat>
 struct is_compatible_float_type
 {
@@ -306,6 +303,7 @@ struct is_compatible_basic_json_type
       std::is_same<typename BasicJson::boolean_t, T>::value or
       is_compatible_array_type<BasicJson, T>::value or
       is_compatible_enum_type<T, typename BasicJson::number_integer_t>::value or
+      is_compatible_enum_type<T, typename BasicJson::number_unsigned_t>::value or
       is_compatible_object_type<typename BasicJson::object_t, T>::value or
       is_compatible_float_type<typename BasicJson::number_float_t, T>::value or
       is_compatible_integer_type<typename BasicJson::number_integer_t,
@@ -1627,8 +1625,8 @@ class basic_json
                             uncvref_t<T>, basic_json_t>::value and
                         not detail::is_basic_json_nested_class<uncvref_t<T>, basic_json_t, primitive_iterator_t>::value and
                         not std::is_same<uncvref_t<T>, typename basic_json_t::array_t::iterator>::value and
-// quickfix
-not std::is_enum<uncvref_t<T>>::value and
+                        not detail::is_compatible_enum_type<number_integer_t, uncvref_t<T>>::value and
+                        not detail::is_compatible_enum_type<number_unsigned_t, uncvref_t<T>>::value and
                         not std::is_same<uncvref_t<T>, typename basic_json_t::object_t::iterator>::value and
                         detail::has_to_json<JSONSerializer, basic_json,
                                             uncvref_t<T>>::value,
@@ -1831,17 +1829,17 @@ not std::is_enum<uncvref_t<T>>::value and
 
     @since version 1.0.0
     */
-    template <
-        typename CompatibleNumberIntegerType,
-        enable_if_t<detail::is_compatible_integer_type<
-                        number_integer_t, CompatibleNumberIntegerType>::value or
-detail::is_compatible_enum_type<number_integer_t, CompatibleNumberIntegerType>::value,
-                    int> = 0>
+    template <typename CompatibleNumberIntegerType,
+              enable_if_t<
+                  detail::is_compatible_integer_type<
+                      number_integer_t, CompatibleNumberIntegerType>::value or
+                      detail::is_compatible_enum_type<
+                          number_integer_t, CompatibleNumberIntegerType>::value,
+                  int> = 0>
     basic_json(const CompatibleNumberIntegerType val) noexcept
         : m_type(value_t::number_integer),
-          m_value(static_cast<number_integer_t>(val))
-    {
-        assert_invariant();
+          m_value(static_cast<number_integer_t>(val)) {
+      assert_invariant();
     }
 
     /*!
@@ -1892,14 +1890,16 @@ detail::is_compatible_enum_type<number_integer_t, CompatibleNumberIntegerType>::
     */
     template <
         typename CompatibleNumberUnsignedType,
-        enable_if_t<detail::is_compatible_integer_type<
-                        number_unsigned_t, CompatibleNumberUnsignedType>::value,
-                    int> = 0>
+        enable_if_t<
+            detail::is_compatible_integer_type<
+                number_unsigned_t, CompatibleNumberUnsignedType>::value or
+                detail::is_compatible_enum_type<
+                    number_integer_t, CompatibleNumberUnsignedType>::value,
+            int> = 0>
     basic_json(const CompatibleNumberUnsignedType val) noexcept
         : m_type(value_t::number_unsigned),
-          m_value(static_cast<number_unsigned_t>(val))
-    {
-        assert_invariant();
+          m_value(static_cast<number_unsigned_t>(val)) {
+      assert_invariant();
     }
 
     /*!
@@ -8603,12 +8603,14 @@ detail::is_compatible_enum_type<number_integer_t, CompatibleNumberIntegerType>::
           return lhs.m_it >= rhs.m_it;
         }
 
-        friend constexpr bool operator+(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+        primitive_iterator_t operator+(difference_type i)
         {
-          return lhs.m_it + rhs.m_it;
+            auto result = *this;
+            result += i;
+            return result;
         }
 
-        friend constexpr bool operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
+        friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
         {
           return lhs.m_it - rhs.m_it;
         }
diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp
index 28443344..2518fcfc 100644
--- a/test/src/unit-udt.cpp
+++ b/test/src/unit-udt.cpp
@@ -85,7 +85,7 @@ namespace udt
   void to_json(nlohmann::json& j, person const& p)
   {
     using nlohmann::json;
-    j = json{{"age", json{p.m_age}}, {"name", json{p.m_name}}};
+    j = json{{"age", p.m_age}, {"name", p.m_name}};
   }
 
   void to_json(nlohmann::json& j, address const& a)
@@ -96,13 +96,13 @@ namespace udt
   void to_json(nlohmann::json& j, contact const& c)
   {
     using nlohmann::json;
-    j = json{{"person", json{c.m_person}}, {"address", json{c.m_address}}};
+    j = json{{"person", c.m_person}, {"address", c.m_address}};
   }
 
   void to_json(nlohmann::json& j, contact_book const& cb)
   {
     using nlohmann::json;
-    j = json{{"name", json{cb.m_book_name}}, {"contacts", cb.m_contacts}};
+    j = json{{"name", cb.m_book_name}, {"contacts", cb.m_contacts}};
   }
 
   // operators
@@ -190,15 +190,15 @@ TEST_CASE("basic usage", "[udt]")
 
   SECTION("conversion to json via free-functions")
   {
-    CHECK(json{a} == json(23));
-    CHECK(json{n} == json("theo"));
-    CHECK(json{sfinae_addict} == R"({"name":"theo", "age":23})"_json);
-    CHECK(json("Paris") == json{addr});
-    CHECK(json{cpp_programmer} ==
+    CHECK(json(a) == json(23));
+    CHECK(json(n) == json("theo"));
+    CHECK(json(sfinae_addict) == R"({"name":"theo", "age":23})"_json);
+    CHECK(json("Paris") == json(addr));
+    CHECK(json(cpp_programmer) ==
           R"({"person" : {"age":23, "name":"theo"}, "address":"Paris"})"_json);
 
     CHECK(
-        json{book} ==
+        json(book) ==
         R"({"name":"C++", "contacts" : [{"person" : {"age":23, "name":"theo"}, "address":"Paris"}, {"person" : {"age":23, "name":"theo"}, "address":"Paris"}]})"_json);
   }