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.
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;
// ...
};
CodePudding user response:
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.