From d0d8070422eed0bd5826a655de5c0be321d285a9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Th=C3=A9o=20DELRIEU?= <delrieutheo@gmail.com>
Date: Thu, 12 Jan 2017 22:52:00 +0100
Subject: [PATCH] add static_asserts

remove some useless trailing return types and && to help MSVC
---
 src/json.hpp | 63 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 58 insertions(+), 5 deletions(-)

diff --git a/src/json.hpp b/src/json.hpp
index 4c6d8671..1188ead4 100644
--- a/src/json.hpp
+++ b/src/json.hpp
@@ -715,27 +715,81 @@ void from_json(Json const &j, ArithmeticType &val)
     throw std::domain_error("type must be number, but is " + type_name(j));
 }
 
+template <typename Json, typename T>
+constexpr auto has_adl_from_json(int) -> decltype(from_json(std::declval<Json const&>(), std::declval<T&>()), true)
+{
+  return true;
+}
+
+template <typename, typename>
+constexpr bool has_adl_from_json(long)
+{
+  return false;
+}
+
+template <typename Json, typename T>
+constexpr auto has_adl_to_json(int) -> decltype(to_json(std::declval<Json&>(), std::declval<T const&>()), true)
+{
+  return true;
+}
+
+template <typename, typename>
+constexpr bool has_adl_to_json(long)
+{
+  return false;
+}
+
 struct to_json_fn
 {
-    template <typename Json, typename T>
-    constexpr auto operator()(Json&& j, T&& val) const
+  private:
+    template <typename Json, typename T, enable_if_t<has_adl_to_json<Json, T>(0), int> = 0>
+    auto operator()(Json&& j, T&& val) const
     noexcept(noexcept(to_json(std::forward<Json>(j), std::forward<T>(val))))
     -> decltype(to_json(std::forward<Json>(j), std::forward<T>(val)),
                 void())
     {
         return to_json(std::forward<Json>(j), std::forward<T>(val));
     }
+
+    template <typename Json, typename T, enable_if_t<not has_adl_to_json<Json, T>(0), int> = 0>
+    void operator()(Json&&, T&&) const noexcept
+    {
+        static_assert(has_adl_to_json<Json, T>(0), "to_json method in T's namespace can not be called");
+    }
+
+public:
+  template <typename Json, typename T>
+  void operator()(Json &j, T &&val) const
+      noexcept(noexcept(std::declval<to_json_fn>().call(0, j, std::forward<T>(val))))
+  {
+      return call(0, j, std::forward<T>(val));
+  }
 };
 
 struct from_json_fn
 {
-    template <typename Json, typename T>
-    constexpr auto operator()(Json&& j, T& val) const
+  private:
+    template <typename Json, typename T, enable_if_t<has_adl_from_json<Json, T>(0), int> = 0>
+    auto operator()(Json&& j, T& val) const
     noexcept(noexcept(from_json(std::forward<Json>(j), val)))
     -> decltype(from_json(std::forward<Json>(j), val), void())
     {
         return from_json(std::forward<Json>(j), val);
     }
+    
+    template <typename Json, typename T, enable_if_t<not has_adl_from_json<Json, T>(0), int> = 0>
+    void operator()(Json&&, T&) const noexcept
+    {
+        static_assert(has_adl_from_json<Json, T>(0), "from_json method in T's namespace can not be called");
+    }
+
+public:
+  template <typename Json, typename T>
+  void operator()(Json const &j, T &val) const
+      noexcept(noexcept(std::declval<from_json_fn>().call(0, j, val)))
+  {
+      return call(0, j, val);
+  }
 };
 
 /*!
@@ -757,7 +811,6 @@ struct DecimalSeparator : std::numpunct<char>
         return '.';
     }
 };
-
 }
 
 // taken from ranges-v3