1 #pragma once
2 
3 #include <iterator> // random_access_iterator_tag
4 
5 #include <nlohmann/detail/meta/void_t.hpp>
6 #include <nlohmann/detail/meta/cpp_future.hpp>
7 
8 namespace nlohmann
9 {
10 namespace detail
11 {
12 template <typename It, typename = void>
13 struct iterator_types {};
14 
15 template <typename It>
16 struct iterator_types<
17     It,
18     void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
19            typename It::reference, typename It::iterator_category>> {
20   using difference_type = typename It::difference_type;
21   using value_type = typename It::value_type;
22   using pointer = typename It::pointer;
23   using reference = typename It::reference;
24   using iterator_category = typename It::iterator_category;
25 };
26 
27 // This is required as some compilers implement std::iterator_traits in a way that
28 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
29 template <typename T, typename = void>
30 struct iterator_traits
31 {
32 };
33 
34 template <typename T>
35 struct iterator_traits<T, enable_if_t<!std::is_pointer<T>::value>>
36   : iterator_types<T>
37 {
38 };
39 
40 template <typename T>
41 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> {
42   using iterator_category = std::random_access_iterator_tag;
43   using value_type = T;
44   using difference_type = ptrdiff_t;
45   using pointer = T*;
46   using reference = T&;
47 };
48 } // namespace detail
49 } // namespace nlohmann
50