Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Why is a map of nlohmann::json values returning an rvalue?

I am using the library nlohmann/json and wish to create an unordered_map of std::string to nlohmann::json.

#include <nlohmann/json.hpp>

class basic_container {
public:
    using key_type = std::string;
    using mapped_type = nlohmann::json;
    using container_type = std::unordered_map<key_type, mapped_type>;
    using reference = typename container_type::reference;
    using const_reference = typename container_type::const_reference;

    // error: cannot bind non-const lvalue reference to an rvalue
    reference at(const key_type &key) {
        return data.at(key);
    }

    // warning: returning reference to temporary
    const_reference at(const key_type &key) const {
        return data.at(key);
    }

    // error: cannot bind non-const lvalue reference to an rvalue
    reference operator[](const key_type &key) {
        return data[key];
    }

private:
    container_type data;
};

The nlohmann::json class is defined in the library similarly to the following.

template<...>
class basic_json {};

using json = basic_json<>;

I can’t figure out why I’m having problems when trying to return a reference or a const reference to a nlohmann::json. The full compiler error for the error: sections within the above code is outlined below.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

error: cannot bind non-const lvalue reference of type 'container::reference' {aka 'std::pair<const std::__cxx11::basic_string<char>, nlohmann::basic_json<> >&'} to an rvalue of type 'std::pair<const std::__cxx11::basic_string<char>, nlohmann::basic_json<> >'

The nicer intellisense error.

a reference of type "container::reference" (not const-qualified) cannot be initialized with a value of type "nlohmann::basic_json<std::map, std::vector, std::string, bool, int64_t, uint64_t, double, std::allocator, nlohmann::adl_serializer, std::vector<uint8_t, std::allocator<uint8_t>>>"

Appreciate any help. Thanks

Edit: The solution was to properly define the aliases. See the following.

class basic_container {
public:
    using key_type = std::string;
    using mapped_type = nlohmann::json;
    using container_type = std::unordered_map<key_type, mapped_type>;
    // using reference = typename container_type::reference;
    // using const_reference = typename container_type::const_reference;
    using reference = typename mapped_type::reference;
    using const_reference = typename mapped_type::const_reference;

    // ...
};

>Solution :

Your wrappers for at(), et. al. are returning the wrong thing.

If you look up the reference for unordered_map::at(): it returns a reference to a (const) T, a.k.a. value_type, a.k.a. your mapped_type.

reference/const_reference is something completely different.

The same problem also happens with your operator[] overload.

P.S. The easiest way to avoid this confusion is to declare your return types as (const-qualified, where appropriate) auto & (in this case). Let your C++ compiler get it right.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading