Compare commits

...
3 Commits
Author SHA1 Message Date
dependabot[bot] 85cb7ea9aa Bump mkdocs-git-revision-date-localized-plugin in /docs/mkdocs (#5168)
Bumps [mkdocs-git-revision-date-localized-plugin](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/releases)
- [Commits](https://github.com/timvink/mkdocs-git-revision-date-localized-plugin/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: mkdocs-git-revision-date-localized-plugin
  dependency-version: 1.5.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-14 09:14:25 +02:00
SamareshSingh 7192763f15 Fix compile error when using nlohmann ordered_map with WITH_DEFAULT macros (#5163)
* Fix compile error when using nlohmann ordered_map with WITH_DEFAULT macros

ordered_map inherits its copy and move assignment from the underlying std vector, which requires value_type to be CopyAssignable. value_type is pair<const Key, T> whose assignment is deleted because of the const Key, so any code that assigns ordered_map (for example the ternary in NLOHMANN_JSON_FROM_WITH_DEFAULT) fails to compile (issue #5122). Provide assignment operators on ordered_map that rebuild via clear plus push_back for copy and transfer the underlying buffer for move, neither of which needs pair assignment. Also switch the map-shaped from_json overload from a transform plus inserter idiom to a range-for plus emplace, which avoids the same hazard.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Update ordered_map.hpp

removed unwanted comments

Signed-off-by: SamareshSingh <97642706+ssam18@users.noreply.github.com>
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Update json.hpp

Signed-off-by: SamareshSingh <97642706+ssam18@users.noreply.github.com>
Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address CI issues for ordered_map fix

Declare an explicit defaulted destructor on ordered_map so the rule of five is complete (clang-tidy cppcoreguidelines-special-member-functions and hicpp-special-member-functions). Initialize the ordered_map field in the regression test struct so GCC effective-C++ stops flagging Example_5122 with a missing member initializer.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Suppress redundant-member-init lint on Example_5122::c

The empty brace-init on c{} is required by GCC -Weffc++ to mark the member as initialized in the synthesized default constructor, but clang-tidy readability-redundant-member-init flags the same line because ordered_map already has a default constructor. The two checks pull in opposite directions, so add a targeted NOLINT to keep both happy.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address review: strong exception safety in copy-assign, simplify move-assign noexcept

Copy assignment now constructs a temporary copy before move-assigning the
Container subobject, preserving *this if the copy throws. Move assignment
uses std::is_nothrow_move_assignable<Container> for a cleaner noexcept
specifier, matching the style of the move constructor.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Restore self-assignment check in copy-assign to satisfy cert-oop54-cpp

clang-tidy's cert-oop54-cpp flagged the previous revision because it could
not recognize the implicit self-safety of the copy-then-move pattern.
Restore the explicit `if (this != &other)` guard — strong exception safety
is preserved since the temporary copy is still constructed before the
move-assign of the Container subobject.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address review: add explicit self-assignment and move-assignment tests for ordered_map

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address review: gate -Wself-assign-overloaded suppression on Clang version

-Wself-assign-overloaded was introduced in Clang 7. Older Clang versions fail the build with "unknown warning group" when the suppression pragma references it unconditionally. Use __has_warning inside an __clang__ branch so the suppression is only emitted on Clang versions that recognize the warning. The inner check stays inside the __clang__ guard because GCC does not provide __has_warning and would tokenize-error on the argument list.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

* Address CI: drop unused gating macro to silence -Wunused-macros

The previous attempt defined JSON_TEST_5122_SUPPRESS_SELF_ASSIGN_OVERLOADED
as 0 unconditionally and then overrode it to 1 on Clang versions that recognize the warning. On those Clangs the initial define is immediately
undef'd without being read, which trips Clang's -Wunused-macros under -Weverything in the ci_test_clang job. Drop the macro and gate the
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH/POP pragmas directly with __has_warning inside the existing __clang__ branch.

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>

---------

Signed-off-by: Samaresh Kumar Singh <ssam3003@gmail.com>
Signed-off-by: SamareshSingh <97642706+ssam18@users.noreply.github.com>
2026-05-14 08:54:24 +02:00
Akhilesh Arora 93e49decbd Fix incomplete-type error in set_parents with ordered_json (#5167)
When iteration_proxy_value<iter_impl<ordered_json>> appears in a context
that requires it to be complete (function or lambda parameter), the
compiler instantiates basic_json<ordered_map> and walks into

    set_parents(iterator, typename iterator::difference_type)

while iterator is still incomplete, failing with "invalid use of
incomplete type".

basic_json::difference_type is already std::ptrdiff_t, so just naming
the underlying type directly avoids the dependent lookup. Behavior and
ABI are unchanged. This was the approach suggested in the issue thread.

Added a regression case in unit-ordered_json.cpp using the same trigger
pattern (lambda parameter naming the proxy type).

Fixes #3732

Signed-off-by: Akhilesh Arora <akhildawra@gmail.com>
2026-05-14 08:52:39 +02:00
7 changed files with 150 additions and 19 deletions

No files matched your search

+1 -1
View File
@@ -1,7 +1,7 @@
wheel==0.47.0
mkdocs==1.6.1 # documentation framework
mkdocs-git-revision-date-localized-plugin==1.5.1 # plugin "git-revision-date-localized"
mkdocs-git-revision-date-localized-plugin==1.5.2 # plugin "git-revision-date-localized"
mkdocs-material==9.7.6 # theme for mkdocs
mkdocs-material-extensions==1.3.1 # extensions
mkdocs-minify-plugin==0.8.0 # plugin "minify"
@@ -388,14 +388,10 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
ConstructibleObjectType ret;
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
using value_type = typename ConstructibleObjectType::value_type;
std::transform(
inner_object->begin(), inner_object->end(),
std::inserter(ret, ret.begin()),
[](typename BasicJsonType::object_t::value_type const & p)
for (const auto& p : *inner_object)
{
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
});
ret.emplace(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
}
obj = std::move(ret);
}
+2 -2
View File
@@ -741,10 +741,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#endif
}
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
iterator set_parents(iterator it, std::ptrdiff_t count_set_parents)
{
#if JSON_DIAGNOSTICS
for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
for (std::ptrdiff_t i = 0; i < count_set_parents; ++i)
{
(it + i)->m_parent = this;
}
+19
View File
@@ -50,6 +50,25 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
: Container{first, last, alloc} {}
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {}
ordered_map(const ordered_map&) = default;
ordered_map(ordered_map&&) noexcept(std::is_nothrow_move_constructible<Container>::value) = default;
~ordered_map() = default;
ordered_map& operator=(const ordered_map& other)
{
if (this != &other)
{
ordered_map tmp(other);
Container::operator=(std::move(static_cast<Container&>(tmp)));
}
return *this;
}
ordered_map& operator=(ordered_map&& other) noexcept(std::is_nothrow_move_assignable<Container>::value)
{
Container::operator=(std::move(static_cast<Container&>(other)));
return *this;
}
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
{
+24 -9
View File
@@ -5306,14 +5306,10 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
ConstructibleObjectType ret;
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
using value_type = typename ConstructibleObjectType::value_type;
std::transform(
inner_object->begin(), inner_object->end(),
std::inserter(ret, ret.begin()),
[](typename BasicJsonType::object_t::value_type const & p)
for (const auto& p : *inner_object)
{
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
});
ret.emplace(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
}
obj = std::move(ret);
}
@@ -20032,6 +20028,25 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
: Container{first, last, alloc} {}
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
: Container{init, alloc} {}
ordered_map(const ordered_map&) = default;
ordered_map(ordered_map&&) noexcept(std::is_nothrow_move_constructible<Container>::value) = default;
~ordered_map() = default;
ordered_map& operator=(const ordered_map& other)
{
if (this != &other)
{
ordered_map tmp(other);
Container::operator=(std::move(static_cast<Container&>(tmp)));
}
return *this;
}
ordered_map& operator=(ordered_map&& other) noexcept(std::is_nothrow_move_assignable<Container>::value)
{
Container::operator=(std::move(static_cast<Container&>(other)));
return *this;
}
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
{
@@ -21020,10 +21035,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
#endif
}
iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
iterator set_parents(iterator it, std::ptrdiff_t count_set_parents)
{
#if JSON_DIAGNOSTICS
for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
for (std::ptrdiff_t i = 0; i < count_set_parents; ++i)
{
(it + i)->m_parent = this;
}
+12
View File
@@ -69,3 +69,15 @@ TEST_CASE("ordered_json")
CHECK(oj1.size() == 4);
CHECK(oj1.dump() == "{\"c\":1,\"b\":2,\"a\":3,\"d\":42}");
}
TEST_CASE("regression test for issue #3732 - iteration_proxy_value<iter_impl<ordered_json>>")
{
// Naming the proxy type in a function-parameter position forces eager
// instantiation of basic_json<ordered_map>; previously this hit an
// incomplete-type error in set_parents().
auto fn = [](nlohmann::detail::iteration_proxy_value<nlohmann::detail::iter_impl<nlohmann::ordered_json>> const& val)
{
return val.value();
};
static_cast<void>(fn);
}
+89
View File
@@ -1240,4 +1240,93 @@ TEST_CASE("regression test #5074 - single-element brace init with JSON_BRACE_INI
}
#endif
struct Example_5122
{
float b = 2;
nlohmann::ordered_map<std::string, std::string> c{}; // NOLINT(readability-redundant-member-init): needed for GCC -Weffc++
int a = 1;
NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Example_5122, b, c, a)
};
TEST_CASE("regression test #5122 - from_json into types holding nlohmann::ordered_map")
{
Example_5122 src;
src.c.emplace("first", "1");
src.c.emplace("second", "2");
ordered_json const j = src;
Example_5122 const dst = j.get<Example_5122>();
CHECK(dst.b == src.b);
CHECK(dst.a == src.a);
REQUIRE(dst.c.size() == src.c.size());
auto src_it = src.c.begin();
auto dst_it = dst.c.begin();
for (; src_it != src.c.end(); ++src_it, ++dst_it)
{
CHECK(dst_it->first == src_it->first);
CHECK(dst_it->second == src_it->second);
}
}
// -Wself-assign-overloaded was introduced in Clang 7. Gate the pragma on
// __has_warning so older Clang versions do not error with "unknown warning
// group". The __has_warning check has to stay inside the __clang__ branch
// because GCC does not provide it and would tokenize-error on the argument.
#if defined(__clang__) && defined(__has_warning)
#if __has_warning("-Wself-assign-overloaded")
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
DOCTEST_CLANG_SUPPRESS_WARNING("-Wself-assign-overloaded")
#endif
#endif
TEST_CASE("regression test #5122 - nlohmann::ordered_map copy-assignment is self-assignment safe")
{
nlohmann::ordered_map<std::string, std::string> m;
m.emplace("first", "1");
m.emplace("second", "2");
// Insertion order is preserved by ordered_map, so we can check it directly.
m = m;
REQUIRE(m.size() == 2);
auto it = m.begin();
CHECK(it->first == "first");
CHECK(it->second == "1");
++it;
CHECK(it->first == "second");
CHECK(it->second == "2");
}
#if defined(__clang__) && defined(__has_warning)
#if __has_warning("-Wself-assign-overloaded")
DOCTEST_CLANG_SUPPRESS_WARNING_POP
#endif
#endif
TEST_CASE("regression test #5122 - nlohmann::ordered_map move-assignment transfers contents")
{
nlohmann::ordered_map<std::string, std::string> src;
src.emplace("first", "1");
src.emplace("second", "2");
nlohmann::ordered_map<std::string, std::string> dst;
dst.emplace("stale", "x");
dst = std::move(src);
REQUIRE(dst.size() == 2);
auto it = dst.begin();
CHECK(it->first == "first");
CHECK(it->second == "1");
++it;
CHECK(it->first == "second");
CHECK(it->second == "2");
// Re-assigning into the moved-from object must leave it in a usable state.
src = nlohmann::ordered_map<std::string, std::string>{};
src.emplace("after-move", "3");
REQUIRE(src.size() == 1);
CHECK(src.begin()->first == "after-move");
}
DOCTEST_CLANG_SUPPRESS_WARNING_POP