Fix VS 2015 build of the DOM parser (#5882) (#5916)

- Name std::hash only once the object type has emplace_new_key: VS 2015
  static-asserts on std::hash of a type without one (alt_string) instead of
  reporting a substitution failure (C2338).
- Replace the std::copy calls on frames by loops: VS 2015 reports raw
  pointers handed to std::copy as C4996, an error under /WX.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann authored and GitHub committed 2026-10-25 12:08:58 +01:00
1 parent d176d8d61e
commit 2a56afc714
2 files changed
+38 -10

No files matched your search

+19 -5
View File
@@ -650,9 +650,17 @@ class json_sax_dom_parser : public json_sax_dom_error_state
/// so that a big object can find the keys it has in a hash table instead of
/// searching all of them
template<typename ObjectType, typename StringType>
using detect_indexable_keys = decltype(std::declval<ObjectType&>().emplace_new_key(std::declval<const StringType&>(), std::declval<typename ObjectType::mapped_type>()),
std::hash<StringType>()(std::declval<const StringType&>()));
static constexpr bool indexed_keys = is_detected<detect_indexable_keys, object_t, string_t>::value;
using detect_emplace_new_key = decltype(std::declval<ObjectType&>().emplace_new_key(std::declval<const StringType&>(), std::declval<typename ObjectType::mapped_type>()));
template<typename StringType>
using detect_hash = decltype(std::hash<StringType>()(std::declval<const StringType&>()));
// std::hash is only named once the object can hold the keys in a vector:
// VS 2015 static-asserts on std::hash of a type without one instead of
// reporting a substitution failure
template<typename ObjectType, typename StringType, bool = is_detected<detect_emplace_new_key, ObjectType, StringType>::value>
struct detect_indexable_keys : std::false_type {};
template<typename ObjectType, typename StringType>
struct detect_indexable_keys<ObjectType, StringType, true> : is_detected<detect_hash, StringType> {};
static constexpr bool indexed_keys = detect_indexable_keys<object_t, string_t>::value;
/// what a frame holds for objects that are kept in a vector: the key index
/// of an object with many keys, and for an object that is collected on the
@@ -774,7 +782,10 @@ class json_sax_dom_parser : public json_sax_dom_error_state
{
const std::size_t new_capacity = capacity * 2;
std::unique_ptr<frame[]> new_heap(new frame[new_capacity]); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
std::copy(data, data + count, new_heap.get());
for (std::size_t i = 0; i < count; ++i)
{
new_heap[i] = data[i];
}
heap = std::move(new_heap);
data = heap.get();
capacity = new_capacity;
@@ -792,7 +803,10 @@ class json_sax_dom_parser : public json_sax_dom_error_state
{
if (other.heap == nullptr)
{
std::copy(other.local.begin(), other.local.begin() + static_cast<std::ptrdiff_t>(other.count), local.begin());
for (std::size_t i = 0; i < other.count; ++i)
{
local[i] = other.local[i];
}
data = local.data();
capacity = local_capacity;
}
+19 -5
View File
@@ -15773,9 +15773,17 @@ class json_sax_dom_parser : public json_sax_dom_error_state
/// so that a big object can find the keys it has in a hash table instead of
/// searching all of them
template<typename ObjectType, typename StringType>
using detect_indexable_keys = decltype(std::declval<ObjectType&>().emplace_new_key(std::declval<const StringType&>(), std::declval<typename ObjectType::mapped_type>()),
std::hash<StringType>()(std::declval<const StringType&>()));
static constexpr bool indexed_keys = is_detected<detect_indexable_keys, object_t, string_t>::value;
using detect_emplace_new_key = decltype(std::declval<ObjectType&>().emplace_new_key(std::declval<const StringType&>(), std::declval<typename ObjectType::mapped_type>()));
template<typename StringType>
using detect_hash = decltype(std::hash<StringType>()(std::declval<const StringType&>()));
// std::hash is only named once the object can hold the keys in a vector:
// VS 2015 static-asserts on std::hash of a type without one instead of
// reporting a substitution failure
template<typename ObjectType, typename StringType, bool = is_detected<detect_emplace_new_key, ObjectType, StringType>::value>
struct detect_indexable_keys : std::false_type {};
template<typename ObjectType, typename StringType>
struct detect_indexable_keys<ObjectType, StringType, true> : is_detected<detect_hash, StringType> {};
static constexpr bool indexed_keys = detect_indexable_keys<object_t, string_t>::value;
/// what a frame holds for objects that are kept in a vector: the key index
/// of an object with many keys, and for an object that is collected on the
@@ -15897,7 +15905,10 @@ class json_sax_dom_parser : public json_sax_dom_error_state
{
const std::size_t new_capacity = capacity * 2;
std::unique_ptr<frame[]> new_heap(new frame[new_capacity]); // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
std::copy(data, data + count, new_heap.get());
for (std::size_t i = 0; i < count; ++i)
{
new_heap[i] = data[i];
}
heap = std::move(new_heap);
data = heap.get();
capacity = new_capacity;
@@ -15915,7 +15926,10 @@ class json_sax_dom_parser : public json_sax_dom_error_state
{
if (other.heap == nullptr)
{
std::copy(other.local.begin(), other.local.begin() + static_cast<std::ptrdiff_t>(other.count), local.begin());
for (std::size_t i = 0; i < other.count; ++i)
{
local[i] = other.local[i];
}
data = local.data();
capacity = local_capacity;
}