Skip to content

ordered_json::emplace(key, value) does not compile when value is an lvalue #5673

Description

@nlohmann

Description

basic_json::emplace(key, value) does not compile for ordered_json when value is an lvalue (or a const lvalue), although the same call compiles for json. It also rejects a single std::pair argument.

basic_json::emplace forwards its arguments to object_t::emplace (include/nlohmann/json.hpp#L4023). std::map::emplace is variadic, but ordered_map only has two overloads whose value parameter is T&& with T being the class template parameter (the mapped type), i.e., an rvalue reference and not a forwarding reference (include/nlohmann/ordered_map.hpp#L73 and #L88):

std::pair<iterator, bool> emplace(const key_type& key, T&& t);

template<class KeyType, ...>
std::pair<iterator, bool> emplace(KeyType && key, T && t);

So only rvalues (including temporaries created by implicit conversion, e.g., oj.emplace("a", 1)) are accepted. The emplace documentation describes template<class... Args> emplace(Args&& ... args) for both json and ordered_json without mentioning this restriction.

Since when: since ordered_json was introduced; v3.9.0 had emplace(key_type&& key, T&& t), and e590604 (v3.9.1) changed the key to const key_type& but kept T&&. The program below fails the same way with the v3.12.0 headers.

Open PR #5609 (head c5d40f0) rewrites how ordered_map::emplace appends, but keeps both signatures; the program below still fails to compile with that PR's ordered_map.hpp.

Possible fix (untested): accept the value by forwarding reference, e.g., template<class V> std::pair<iterator, bool> emplace(const key_type& key, V&& t) constrained on std::is_constructible<T, V&&>, and likewise for the KeyType overload; alternatively add emplace(const key_type&, const T&) overloads. A variadic emplace(Args&&...) like std::map's would also cover the std::pair form, but needs to extract the key before constructing the element.

Reproduction steps

  1. Save the program below as c05.cpp.
  2. Compile it against develop: clang++ -std=c++17 -I include c05.cpp -o c05 (the same error occurs with -std=c++11 and with GCC 16.2).

Expected vs. actual results

  • Expected: the program compiles and prints {"a":1} {"a":1}.
  • Actual: compile error in basic_json::emplace for the ordered_json call.

Minimal code example

#include <nlohmann/json.hpp>
#include <iostream>

using nlohmann::json;
using nlohmann::ordered_json;

int main()
{
    json j = json::object();
    json value = 1;
    j.emplace("a", value);    // compiles

    ordered_json oj = ordered_json::object();
    ordered_json ovalue = 1;
    oj.emplace("a", ovalue);  // expected: compiles like the json version
                              // actual:   error: no matching member function for call to 'emplace'

    std::cout << j << ' ' << oj << '\n';
}

Error messages

include/nlohmann/json.hpp:4023:43: error: no matching member function for call to 'emplace'
 4023 |         auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
      |                    ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~
c05.cpp:15:8: note: in instantiation of function template specialization 'nlohmann::basic_json<nlohmann::ordered_map>::emplace<const char (&)[2], nlohmann::basic_json<nlohmann::ordered_map> &>' requested here
include/nlohmann/ordered_map.hpp:88:31: note: candidate function template not viable: expects an rvalue for 2nd argument
include/nlohmann/ordered_map.hpp:73:31: note: candidate function not viable: expects an rvalue for 2nd argument
1 error generated.

With GCC 16.2:

include/nlohmann/json.hpp:4023:50: error: no matching function for call to 'nlohmann::json_abi_v3_12_0::ordered_map<...>::emplace(const char [2], nlohmann::json_abi_v3_12_0::basic_json<nlohmann::json_abi_v3_12_0::ordered_map>&)'
      • error: cannot bind rvalue reference of type 'nlohmann::json_abi_v3_12_0::basic_json<nlohmann::json_abi_v3_12_0::ordered_map>&&' to lvalue of type 'nlohmann::json_abi_v3_12_0::basic_json<nlohmann::json_abi_v3_12_0::ordered_map>'

Compiler and operating system

Apple clang 21.0.0 (clang-2100.3.34.2), macOS 27.0 (arm64); also GCC 16.2 (/opt/homebrew/bin/g++-16)

Library version

develop @ 633de8e; also 3.12.0

Validation

  • The bug also occurs if the latest version from the develop branch is used.
  • I can successfully compile and run the unit tests.

This issue was written by Claude Code on behalf of @nlohmann.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

kind: bugsolution: proposed fixa fix for the issue has been proposed and waits for confirmation

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions