From 2c23f0a34600ce54a1687004b9557079046e5b6e Mon Sep 17 00:00:00 2001
From: David Avedissian <git@dga.me.uk>
Date: Sat, 8 Dec 2018 15:46:33 +0000
Subject: [PATCH] Changes requested from code review.

---
 .../detail/iterators/iterator_traits.hpp      | 36 +++++++++---------
 single_include/nlohmann/json.hpp              | 38 ++++++++++---------
 2 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/include/nlohmann/detail/iterators/iterator_traits.hpp b/include/nlohmann/detail/iterators/iterator_traits.hpp
index 43603988..607dd49a 100644
--- a/include/nlohmann/detail/iterators/iterator_traits.hpp
+++ b/include/nlohmann/detail/iterators/iterator_traits.hpp
@@ -3,16 +3,17 @@
 #include <iterator> // random_access_iterator_tag
 
 #include <nlohmann/detail/meta/void_t.hpp>
+#include <nlohmann/detail/meta/cpp_future.hpp>
 
 namespace nlohmann
 {
 namespace detail
 {
-template <class It, class = void>
-struct _iterator_types {};
+template <typename It, typename = void>
+struct iterator_types {};
 
-template <class It>
-struct _iterator_types<
+template <typename It>
+struct iterator_types<
     It,
     void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
            typename It::reference, typename It::iterator_category>> {
@@ -23,25 +24,26 @@ struct _iterator_types<
   using iterator_category = typename It::iterator_category;
 };
 
-template <class Iter>
-struct iterator_traits : _iterator_types<Iter> {};
+// This is required as some compilers implement std::iterator_traits in a way that
+// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
+template <typename T, typename = void>
+struct iterator_traits
+{
+};
 
-template <class T>
-struct iterator_traits<T*> {
+template <typename T>
+struct iterator_traits<T, enable_if_t<!std::is_pointer<T>::value>>
+  : iterator_types<T>
+{
+};
+
+template <typename T>
+struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> {
   typedef std::random_access_iterator_tag iterator_category;
   typedef T value_type;
   typedef ptrdiff_t difference_type;
   typedef T* pointer;
   typedef T& reference;
 };
-
-template <class T>
-struct iterator_traits<const T*> {
-  typedef std::random_access_iterator_tag iterator_category;
-  typedef T value_type;
-  typedef ptrdiff_t difference_type;
-  typedef const T* pointer;
-  typedef const T& reference;
-};
 }
 }
\ No newline at end of file
diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp
index 8ef906d6..24ff17b8 100644
--- a/single_include/nlohmann/json.hpp
+++ b/single_include/nlohmann/json.hpp
@@ -344,16 +344,18 @@ template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
 } // namespace detail
 }  // namespace nlohmann
 
+// #include <nlohmann/detail/meta/cpp_future.hpp>
+
 
 namespace nlohmann
 {
 namespace detail
 {
-template <class It, class = void>
-struct _iterator_types {};
+template <typename It, typename = void>
+struct iterator_types {};
 
-template <class It>
-struct _iterator_types <
+template <typename It>
+struct iterator_types <
     It,
     void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
     typename It::reference, typename It::iterator_category >>
@@ -365,11 +367,21 @@ struct _iterator_types <
     using iterator_category = typename It::iterator_category;
 };
 
-template <class Iter>
-struct iterator_traits : _iterator_types<Iter> {};
+// This is required due to https://github.com/nlohmann/json/issues/1341 - where some
+// compilers implement std::iterator_traits in a way that doesn't work with SFINAE.
+template <typename T, typename = void>
+struct iterator_traits
+{
+};
 
-template <class T>
-struct iterator_traits<T*>
+template <typename T>
+struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
+            : iterator_types<T>
+{
+};
+
+template <typename T>
+struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
 {
     typedef std::random_access_iterator_tag iterator_category;
     typedef T value_type;
@@ -377,16 +389,6 @@ struct iterator_traits<T*>
     typedef T* pointer;
     typedef T& reference;
 };
-
-template <class T>
-struct iterator_traits<const T*>
-{
-    typedef std::random_access_iterator_tag iterator_category;
-    typedef T value_type;
-    typedef ptrdiff_t difference_type;
-    typedef const T* pointer;
-    typedef const T& reference;
-};
 }
 }
 // #include <nlohmann/detail/meta/cpp_future.hpp>