From 2a56afc714d485870ae41cb1ac4fb0556f86726b Mon Sep 17 00:00:00 2001 From: Niels Lohmann Date: Sun, 25 Oct 2026 12:08:58 +0100 Subject: [PATCH] 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 --- include/nlohmann/detail/input/json_sax.hpp | 24 +++++++++++++++++----- single_include/nlohmann/json.hpp | 24 +++++++++++++++++----- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/include/nlohmann/detail/input/json_sax.hpp b/include/nlohmann/detail/input/json_sax.hpp index 6fd0be52d..04201efbe 100644 --- a/include/nlohmann/detail/input/json_sax.hpp +++ b/include/nlohmann/detail/input/json_sax.hpp @@ -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 - using detect_indexable_keys = decltype(std::declval().emplace_new_key(std::declval(), std::declval()), - std::hash()(std::declval())); - static constexpr bool indexed_keys = is_detected::value; + using detect_emplace_new_key = decltype(std::declval().emplace_new_key(std::declval(), std::declval())); + template + using detect_hash = decltype(std::hash()(std::declval())); + // 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::value> + struct detect_indexable_keys : std::false_type {}; + template + struct detect_indexable_keys : is_detected {}; + static constexpr bool indexed_keys = detect_indexable_keys::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 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(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; } diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index a9e40693d..1beba149b 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -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 - using detect_indexable_keys = decltype(std::declval().emplace_new_key(std::declval(), std::declval()), - std::hash()(std::declval())); - static constexpr bool indexed_keys = is_detected::value; + using detect_emplace_new_key = decltype(std::declval().emplace_new_key(std::declval(), std::declval())); + template + using detect_hash = decltype(std::hash()(std::declval())); + // 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::value> + struct detect_indexable_keys : std::false_type {}; + template + struct detect_indexable_keys : is_detected {}; + static constexpr bool indexed_keys = detect_indexable_keys::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 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(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; }