diff --git a/include/nlohmann/detail/input/input_adapters.hpp b/include/nlohmann/detail/input/input_adapters.hpp index b16183ef..91215a96 100644 --- a/include/nlohmann/detail/input/input_adapters.hpp +++ b/include/nlohmann/detail/input/input_adapters.hpp @@ -360,7 +360,7 @@ class input_adapter /// input adapter for iterator range with contiguous storage template::iterator_category, std::random_access_iterator_tag>::value, + std::is_same::iterator_category, std::random_access_iterator_tag>::value, int>::type = 0> input_adapter(IteratorType first, IteratorType last) { @@ -379,7 +379,7 @@ class input_adapter // assertion to check that each element is 1 byte long static_assert( - sizeof(typename std::iterator_traits::value_type) == 1, + sizeof(typename iterator_traits::value_type) == 1, "each element in the iterator range must have the size of 1 byte"); const auto len = static_cast(std::distance(first, last)); @@ -403,7 +403,7 @@ class input_adapter /// input adapter for contiguous container template::value and - std::is_base_of()))>::iterator_category>::value, + std::is_base_of()))>::iterator_category>::value, int>::type = 0> input_adapter(const ContiguousContainer& c) : input_adapter(std::begin(c), std::end(c)) {} diff --git a/include/nlohmann/detail/iterators/iterator_traits.hpp b/include/nlohmann/detail/iterators/iterator_traits.hpp new file mode 100644 index 00000000..35ea81fb --- /dev/null +++ b/include/nlohmann/detail/iterators/iterator_traits.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include // random_access_iterator_tag + +#include +#include + +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; + +template +struct iterator_types< + It, + void_t> { + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// 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 +struct iterator_traits +{ +}; + +template +struct iterator_traits::value>> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> { + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} +} diff --git a/include/nlohmann/detail/meta/type_traits.hpp b/include/nlohmann/detail/meta/type_traits.hpp index d901f1e0..ee04da22 100644 --- a/include/nlohmann/detail/meta/type_traits.hpp +++ b/include/nlohmann/detail/meta/type_traits.hpp @@ -6,6 +6,7 @@ #include // declval #include +#include #include #include #include @@ -131,10 +132,10 @@ template struct is_iterator_traits : std::false_type {}; template -struct is_iterator_traits> +struct is_iterator_traits> { private: - using traits = std::iterator_traits; + using traits = iterator_traits; public: static constexpr auto value = @@ -251,7 +252,7 @@ struct is_compatible_array_type_impl < // Therefore it is detected as a CompatibleArrayType. // The real fix would be to have an Iterable concept. not is_iterator_traits< - std::iterator_traits>::value >> + iterator_traits>::value >> { static constexpr bool value = std::is_constructible>::value and + iterator_traits>::value and (std::is_same::value or has_from_json // hash, less #include // initializer_list #include // istream, ostream -#include // iterator_traits, random_access_iterator_tag +#include // random_access_iterator_tag #include // accumulate #include // string, stoi, to_string #include // declval, forward, move, pair, swap diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index f044d3a2..081d897a 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -41,7 +41,7 @@ SOFTWARE. #include // hash, less #include // initializer_list #include // istream, ostream -#include // iterator_traits, random_access_iterator_tag +#include // random_access_iterator_tag #include // accumulate #include // string, stoi, to_string #include // declval, forward, move, pair, swap @@ -324,12 +324,10 @@ constexpr T static_const::value; // #include -// #include - -// #include +// #include -#include +#include // random_access_iterator_tag // #include @@ -346,6 +344,63 @@ template using void_t = typename make_void::type; } // namespace detail } // namespace nlohmann +// #include + + +namespace nlohmann +{ +namespace detail +{ +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// 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 +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; +} +} + +// #include + +// #include + + +#include + +// #include + // http://en.cppreference.com/w/cpp/experimental/is_detected namespace nlohmann @@ -522,10 +577,10 @@ template struct is_iterator_traits : std::false_type {}; template -struct is_iterator_traits> +struct is_iterator_traits> { private: - using traits = std::iterator_traits; + using traits = iterator_traits; public: static constexpr auto value = @@ -642,7 +697,7 @@ struct is_compatible_array_type_impl < // Therefore it is detected as a CompatibleArrayType. // The real fix would be to have an Iterable concept. not is_iterator_traits< - std::iterator_traits>::value >> + iterator_traits>::value >> { static constexpr bool value = std::is_constructible>::value and + iterator_traits>::value and (std::is_same::value or has_from_json::iterator_category, std::random_access_iterator_tag>::value, + std::is_same::iterator_category, std::random_access_iterator_tag>::value, int>::type = 0> input_adapter(IteratorType first, IteratorType last) { @@ -2428,7 +2483,7 @@ class input_adapter // assertion to check that each element is 1 byte long static_assert( - sizeof(typename std::iterator_traits::value_type) == 1, + sizeof(typename iterator_traits::value_type) == 1, "each element in the iterator range must have the size of 1 byte"); const auto len = static_cast(std::distance(first, last)); @@ -2452,7 +2507,7 @@ class input_adapter /// input adapter for contiguous container template::value and - std::is_base_of()))>::iterator_category>::value, + std::is_base_of()))>::iterator_category>::value, int>::type = 0> input_adapter(const ContiguousContainer& c) : input_adapter(std::begin(c), std::end(c)) {}