Implement SFINAE friendly iterator_traits and use that instead.
This commit is contained in:
parent
e3c28afb61
commit
f665a92330
5 changed files with 120 additions and 20 deletions
|
@ -331,7 +331,7 @@ class input_adapter
|
||||||
/// input adapter for iterator range with contiguous storage
|
/// input adapter for iterator range with contiguous storage
|
||||||
template<class IteratorType,
|
template<class IteratorType,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
|
std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
|
||||||
int>::type = 0>
|
int>::type = 0>
|
||||||
input_adapter(IteratorType first, IteratorType last)
|
input_adapter(IteratorType first, IteratorType last)
|
||||||
{
|
{
|
||||||
|
@ -350,7 +350,7 @@ class input_adapter
|
||||||
|
|
||||||
// assertion to check that each element is 1 byte long
|
// assertion to check that each element is 1 byte long
|
||||||
static_assert(
|
static_assert(
|
||||||
sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
|
sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
|
||||||
"each element in the iterator range must have the size of 1 byte");
|
"each element in the iterator range must have the size of 1 byte");
|
||||||
|
|
||||||
const auto len = static_cast<size_t>(std::distance(first, last));
|
const auto len = static_cast<size_t>(std::distance(first, last));
|
||||||
|
@ -374,7 +374,7 @@ class input_adapter
|
||||||
/// input adapter for contiguous container
|
/// input adapter for contiguous container
|
||||||
template<class ContiguousContainer, typename
|
template<class ContiguousContainer, typename
|
||||||
std::enable_if<not std::is_pointer<ContiguousContainer>::value and
|
std::enable_if<not std::is_pointer<ContiguousContainer>::value and
|
||||||
std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
|
std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
|
||||||
int>::type = 0>
|
int>::type = 0>
|
||||||
input_adapter(const ContiguousContainer& c)
|
input_adapter(const ContiguousContainer& c)
|
||||||
: input_adapter(std::begin(c), std::end(c)) {}
|
: input_adapter(std::begin(c), std::end(c)) {}
|
||||||
|
|
47
include/nlohmann/detail/iterators/iterator_traits.hpp
Normal file
47
include/nlohmann/detail/iterators/iterator_traits.hpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iterator> // random_access_iterator_tag
|
||||||
|
|
||||||
|
#include <nlohmann/detail/meta/void_t.hpp>
|
||||||
|
|
||||||
|
namespace nlohmann
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <class It, class = void>
|
||||||
|
struct _iterator_types {};
|
||||||
|
|
||||||
|
template <class 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>> {
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
struct iterator_traits : _iterator_types<Iter> {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct iterator_traits<T*> {
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
#include <utility> // declval
|
#include <utility> // declval
|
||||||
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
#include <nlohmann/detail/meta/detected.hpp>
|
#include <nlohmann/detail/meta/detected.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
@ -131,10 +132,10 @@ template <typename T, typename = void>
|
||||||
struct is_iterator_traits : std::false_type {};
|
struct is_iterator_traits : std::false_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_iterator_traits<std::iterator_traits<T>>
|
struct is_iterator_traits<iterator_traits<T>>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using traits = std::iterator_traits<T>;
|
using traits = iterator_traits<T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr auto value =
|
static constexpr auto value =
|
||||||
|
@ -251,7 +252,7 @@ struct is_compatible_array_type_impl <
|
||||||
// Therefore it is detected as a CompatibleArrayType.
|
// Therefore it is detected as a CompatibleArrayType.
|
||||||
// The real fix would be to have an Iterable concept.
|
// The real fix would be to have an Iterable concept.
|
||||||
not is_iterator_traits<
|
not is_iterator_traits<
|
||||||
std::iterator_traits<CompatibleArrayType>>::value >>
|
iterator_traits<CompatibleArrayType>>::value >>
|
||||||
{
|
{
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
std::is_constructible<BasicJsonType,
|
std::is_constructible<BasicJsonType,
|
||||||
|
@ -288,7 +289,7 @@ struct is_constructible_array_type_impl <
|
||||||
// Therefore it is detected as a ConstructibleArrayType.
|
// Therefore it is detected as a ConstructibleArrayType.
|
||||||
// The real fix would be to have an Iterable concept.
|
// The real fix would be to have an Iterable concept.
|
||||||
not is_iterator_traits <
|
not is_iterator_traits <
|
||||||
std::iterator_traits<ConstructibleArrayType >>::value and
|
iterator_traits<ConstructibleArrayType >>::value and
|
||||||
|
|
||||||
(std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
|
(std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
|
||||||
has_from_json<BasicJsonType,
|
has_from_json<BasicJsonType,
|
||||||
|
|
|
@ -41,7 +41,7 @@ SOFTWARE.
|
||||||
#include <functional> // hash, less
|
#include <functional> // hash, less
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#include <iosfwd> // istream, ostream
|
#include <iosfwd> // istream, ostream
|
||||||
#include <iterator> // iterator_traits, random_access_iterator_tag
|
#include <iterator> // random_access_iterator_tag
|
||||||
#include <numeric> // accumulate
|
#include <numeric> // accumulate
|
||||||
#include <string> // string, stoi, to_string
|
#include <string> // string, stoi, to_string
|
||||||
#include <utility> // declval, forward, move, pair, swap
|
#include <utility> // declval, forward, move, pair, swap
|
||||||
|
|
|
@ -41,7 +41,7 @@ SOFTWARE.
|
||||||
#include <functional> // hash, less
|
#include <functional> // hash, less
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#include <iosfwd> // istream, ostream
|
#include <iosfwd> // istream, ostream
|
||||||
#include <iterator> // iterator_traits, random_access_iterator_tag
|
#include <iterator> // random_access_iterator_tag
|
||||||
#include <numeric> // accumulate
|
#include <numeric> // accumulate
|
||||||
#include <string> // string, stoi, to_string
|
#include <string> // string, stoi, to_string
|
||||||
#include <utility> // declval, forward, move, pair, swap
|
#include <utility> // declval, forward, move, pair, swap
|
||||||
|
@ -324,12 +324,10 @@ constexpr T static_const<T>::value;
|
||||||
|
|
||||||
// #include <nlohmann/json_fwd.hpp>
|
// #include <nlohmann/json_fwd.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/meta/cpp_future.hpp>
|
// #include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||||
|
|
||||||
// #include <nlohmann/detail/meta/detected.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
#include <type_traits>
|
#include <iterator> // random_access_iterator_tag
|
||||||
|
|
||||||
// #include <nlohmann/detail/meta/void_t.hpp>
|
// #include <nlohmann/detail/meta/void_t.hpp>
|
||||||
|
|
||||||
|
@ -347,6 +345,60 @@ template <typename ...Ts> using void_t = typename make_void<Ts...>::type;
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
||||||
|
|
||||||
|
|
||||||
|
namespace nlohmann
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template <class It, class = void>
|
||||||
|
struct _iterator_types {};
|
||||||
|
|
||||||
|
template <class 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 >>
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class Iter>
|
||||||
|
struct iterator_traits : _iterator_types<Iter> {};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct iterator_traits<T*>
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/meta/detected.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
// #include <nlohmann/detail/meta/void_t.hpp>
|
||||||
|
|
||||||
|
|
||||||
// http://en.cppreference.com/w/cpp/experimental/is_detected
|
// http://en.cppreference.com/w/cpp/experimental/is_detected
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
{
|
{
|
||||||
|
@ -522,10 +574,10 @@ template <typename T, typename = void>
|
||||||
struct is_iterator_traits : std::false_type {};
|
struct is_iterator_traits : std::false_type {};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct is_iterator_traits<std::iterator_traits<T>>
|
struct is_iterator_traits<iterator_traits<T>>
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
using traits = std::iterator_traits<T>;
|
using traits = iterator_traits<T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr auto value =
|
static constexpr auto value =
|
||||||
|
@ -642,7 +694,7 @@ struct is_compatible_array_type_impl <
|
||||||
// Therefore it is detected as a CompatibleArrayType.
|
// Therefore it is detected as a CompatibleArrayType.
|
||||||
// The real fix would be to have an Iterable concept.
|
// The real fix would be to have an Iterable concept.
|
||||||
not is_iterator_traits<
|
not is_iterator_traits<
|
||||||
std::iterator_traits<CompatibleArrayType>>::value >>
|
iterator_traits<CompatibleArrayType>>::value >>
|
||||||
{
|
{
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
std::is_constructible<BasicJsonType,
|
std::is_constructible<BasicJsonType,
|
||||||
|
@ -679,7 +731,7 @@ struct is_constructible_array_type_impl <
|
||||||
// Therefore it is detected as a ConstructibleArrayType.
|
// Therefore it is detected as a ConstructibleArrayType.
|
||||||
// The real fix would be to have an Iterable concept.
|
// The real fix would be to have an Iterable concept.
|
||||||
not is_iterator_traits <
|
not is_iterator_traits <
|
||||||
std::iterator_traits<ConstructibleArrayType >>::value and
|
iterator_traits<ConstructibleArrayType >>::value and
|
||||||
|
|
||||||
(std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
|
(std::is_same<typename ConstructibleArrayType::value_type, typename BasicJsonType::array_t::value_type>::value or
|
||||||
has_from_json<BasicJsonType,
|
has_from_json<BasicJsonType,
|
||||||
|
@ -2380,7 +2432,7 @@ class input_adapter
|
||||||
/// input adapter for iterator range with contiguous storage
|
/// input adapter for iterator range with contiguous storage
|
||||||
template<class IteratorType,
|
template<class IteratorType,
|
||||||
typename std::enable_if<
|
typename std::enable_if<
|
||||||
std::is_same<typename std::iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
|
std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
|
||||||
int>::type = 0>
|
int>::type = 0>
|
||||||
input_adapter(IteratorType first, IteratorType last)
|
input_adapter(IteratorType first, IteratorType last)
|
||||||
{
|
{
|
||||||
|
@ -2399,7 +2451,7 @@ class input_adapter
|
||||||
|
|
||||||
// assertion to check that each element is 1 byte long
|
// assertion to check that each element is 1 byte long
|
||||||
static_assert(
|
static_assert(
|
||||||
sizeof(typename std::iterator_traits<IteratorType>::value_type) == 1,
|
sizeof(typename iterator_traits<IteratorType>::value_type) == 1,
|
||||||
"each element in the iterator range must have the size of 1 byte");
|
"each element in the iterator range must have the size of 1 byte");
|
||||||
|
|
||||||
const auto len = static_cast<size_t>(std::distance(first, last));
|
const auto len = static_cast<size_t>(std::distance(first, last));
|
||||||
|
@ -2423,7 +2475,7 @@ class input_adapter
|
||||||
/// input adapter for contiguous container
|
/// input adapter for contiguous container
|
||||||
template<class ContiguousContainer, typename
|
template<class ContiguousContainer, typename
|
||||||
std::enable_if<not std::is_pointer<ContiguousContainer>::value and
|
std::enable_if<not std::is_pointer<ContiguousContainer>::value and
|
||||||
std::is_base_of<std::random_access_iterator_tag, typename std::iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
|
std::is_base_of<std::random_access_iterator_tag, typename iterator_traits<decltype(std::begin(std::declval<ContiguousContainer const>()))>::iterator_category>::value,
|
||||||
int>::type = 0>
|
int>::type = 0>
|
||||||
input_adapter(const ContiguousContainer& c)
|
input_adapter(const ContiguousContainer& c)
|
||||||
: input_adapter(std::begin(c), std::end(c)) {}
|
: input_adapter(std::begin(c), std::end(c)) {}
|
||||||
|
|
Loading…
Reference in a new issue