Accept lvalues in ordered_map::emplace's value parameter

ordered_map::emplace(key, value) took the mapped value only by T&&, an
rvalue reference rather than a forwarding reference, so
ordered_json::emplace("a", value) failed to compile whenever value was
an lvalue or a const lvalue, even though the same call compiles for
json (whose object_t is std::map, with a variadic emplace). Turn the
value parameter into a separately-deduced forwarding reference,
constrained with std::is_constructible so the overloads still only
accept something convertible to the mapped type. std::map-compatible
semantics are unchanged: emplace still does nothing if the key already
exists.

Open PR #5609 also touches ordered_map.hpp (moving values on vector
growth); this change only touches the two emplace() overloads and
should not conflict.

Fixes #5673.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann
2026-09-29 23:19:59 +02:00
parent 633de8e44b
commit 989b8ed841
5 changed files with 134 additions and 12 deletions
+41
View File
@@ -196,3 +196,44 @@ TEST_CASE("regression test - diff() must account for ordered_json member order")
CHECK(a.patch(p) == b);
}
}
TEST_CASE("regression test for issue #5673 - ordered_json::emplace with a non-rvalue value")
{
SECTION("lvalue value")
{
ordered_json oj = ordered_json::object();
ordered_json value = 1;
auto res = oj.emplace("a", value);
CHECK(res.second == true);
CHECK(oj.dump() == "{\"a\":1}");
}
SECTION("const lvalue value")
{
ordered_json oj = ordered_json::object();
const ordered_json value = 1;
auto res = oj.emplace("a", value);
CHECK(res.second == true);
CHECK(oj.dump() == "{\"a\":1}");
}
SECTION("rvalue value")
{
ordered_json oj = ordered_json::object();
auto res = oj.emplace("a", ordered_json(1));
CHECK(res.second == true);
CHECK(oj.dump() == "{\"a\":1}");
}
SECTION("existing key is not overwritten (std::map-compatible semantics)")
{
ordered_json oj = ordered_json::object();
ordered_json value = 1;
oj.emplace("a", value);
ordered_json other_value = 2;
auto res = oj.emplace("a", other_value);
CHECK(res.second == false);
CHECK(oj.dump() == "{\"a\":1}");
}
}