I'm using the nlohmann/json
library and trying to implement serialization and deserialization for one of my structs. I'm going by this example.
This is the struct and the relevant types:
typedef std::uint32_t vertex_key;
typedef std::uint64_t edge_key;
inline edge_key get_edge_key(vertex_key v1, vertex_key v2) {
return (std::uint64_t)v1 << 32 | (std::uint64_t)v2; // edge 64b = (v1 32b, v2 32b)
}
struct Mcnfmq {
unsigned int n_nodes;
vertex_key source;
vertex_key sink;
unsigned int flow_value;
std::unordered_map<edge_key, int> costs;
std::unordered_map<edge_key, int> capacities;
std::unordered_map<edge_key, int> minimum_quantities;
Mcnfmq(unsigned int n_nodes, vertex_key source, vertex_key sink, unsigned int flow_value)
: n_nodes(n_nodes), source(source), sink(sink), flow_value(flow_value) {}
};
void to_json(json& j, const Mcnfmq& instance);
void from_json(const json& j, Mcnfmq& instance);
Here are the to/from implementations:
void to_json(json& j, const Mcnfmq& instance) {
j = json{
{"n_nodes", instance.n_nodes},
{"source", instance.source},
{"sink", instance.sink},
{"flow_value", instance.flow_value},
{"costs", instance.costs},
{"capacities", instance.capacities},
{"minimum_quantities", instance.minimum_quantities},
};
}
void from_json(const json& j, Mcnfmq& instance) {
j.at("n_nodes").get_to(instance.n_nodes);
j.at("source").get_to(instance.source);
j.at("sink").get_to(instance.sink);
j.at("flow_value").get_to(instance.flow_value);
j.at("costs").get_to(instance.costs);
j.at("capacities").get_to(instance.capacities);
j.at("minimum_quantities").get_to(instance.minimum_quantities);
}
The struct Mcnfmq
and functions to_json
and from_json
obviously reside in the same namespace (global), so that shouldn't be an issue.
This is the main file:
int main() {
std::ifstream i("output.json");
json j2;
i >> j2;
i.close();
Mcnfmq instance2 = j2.get<Mcnfmq>(); // ERROR HERE
return 0;
}
Full error output:
test_serialization.cpp: In function 'int main()':
test_serialization.cpp:27:38: error: no matching function for call to 'nlohmann::basic_json<>::get<Mcnfmq>()'
27 | Mcnfmq instance2 = j2.get<Mcnfmq>();
| ~~~~~~~~~~~~~~^~
In file included from test_serialization.cpp:6:
json.hpp:20717:10: note: candidate: 'template<class ValueTypeCV, class ValueType> constexpr decltype (declval<const basic_json_t&>().get_impl<ValueType>(nlohmann::detail::priority_tag<4>{})) nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::get() const [with ValueTypeCV = ValueTypeCV; ValueType = ValueType; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; BinaryType = std::vector<unsigned char>]'
20717 | auto get() const noexcept(
| ^~~
json.hpp:20717:10: note: template argument deduction/substitution failed:
json.hpp: In substitution of 'template<class ValueTypeCV, class ValueType> constexpr decltype (declval<const basic_json_t&>().get_impl<ValueType>(nlohmann::detail::priority_tag<4>{})) nlohmann::basic_json<>::get<ValueTypeCV, ValueType>() const [with ValueTypeCV = Mcnfmq; ValueType = Mcnfmq]':
test_serialization.cpp:27:38: required from here
json.hpp:20719:81: error: no matching function for call to 'nlohmann::basic_json<>::get_impl<Mcnfmq>(nlohmann::detail::priority_tag<4>) const'
20719 | -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
json.hpp:20579:15: note: candidate: 'template<class ValueType, typename std::enable_if<(nlohmann::detail::is_default_constructible<T1>::value && nlohmann::detail::has_from_json<nlohmann::basic_json<>, ValueType, void>::value), int>::type <anonymous> > ValueType nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::get_impl(nlohmann::detail::priority_tag<0>) const [with ValueType = ValueType; typename std::enable_if<(nlohmann::detail::is_default_constructible<ValueType>::value && nlohmann::detail::has_from_json<nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>, ValueType>::value), int>::type <anonymous> = <anonymous>; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; BinaryType = std::vector<unsigned char>]'
20579 | ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
| ^~~~~~~~
json.hpp:20579:15: note: template argument deduction/substitution failed:
json.hpp:20578:28: error: no type named 'type' in 'struct std::enable_if<false, int>'
20578 | int > = 0 >
| ^
json.hpp:20621:15: note: candidate: 'template<class ValueType, typename std::enable_if<nlohmann::detail::has_non_default_from_json<nlohmann::basic_json<>, ValueType, void>::value, int>::type <anonymous> > ValueType nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::get_impl(nlohmann::detail::priority_tag<1>) const [with ValueType = ValueType; typename std::enable_if<nlohmann::detail::has_non_default_from_json<nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>, ValueType>::value, int>::type <anonymous> = <anonymous>; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; BinaryType = std::vector<unsigned char>]'
20621 | ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
| ^~~~~~~~
json.hpp:20621:15: note: template argument deduction/substitution failed:
json.hpp:20620:28: error: no type named 'type' in 'struct std::enable_if<false, int>'
20620 | int > = 0 >
| ^
json.hpp:20646:19: note: candidate: 'template<class BasicJsonType, typename std::enable_if<nlohmann::detail::is_basic_json<BasicJsonType>::value, int>::type <anonymous> > BasicJsonType nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::get_impl(nlohmann::detail::priority_tag<2>) const [with BasicJsonType = BasicJsonType; typename std::enable_if<nlohmann::detail::is_basic_json<BasicJsonType>::value, int>::type <anonymous> = <anonymous>; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; BinaryType = std::vector<unsigned char>]'
20646 | BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
| ^~~~~~~~
json.hpp:20646:19: note: template argument deduction/substitution failed:
json.hpp:20645:28: error: no type named 'type' in 'struct std::enable_if<false, int>'
20645 | int > = 0 >
| ^
json.hpp:20669:16: note: candidate: 'template<class BasicJsonType, typename std::enable_if<std::is_same<BasicJsonType, nlohmann::basic_json<> >::value, int>::type <anonymous> > nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType> nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::get_impl(nlohmann::detail::priority_tag<3>) const [with BasicJsonType = BasicJsonType; typename std::enable_if<std::is_same<BasicJsonType, nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType> >::value, int>::type <anonymous> = <anonymous>; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; BinaryType = std::vector<unsigned char>]'
20669 | basic_json get_impl(detail::priority_tag<3> /*unused*/) const
| ^~~~~~~~
json.hpp:20669:16: note: template argument deduction/substitution failed:
json.hpp:20668:25: error: no type named 'type' in 'struct std::enable_if<false, int>'
20668 | int> = 0>
| ^
json.hpp:20682:20: note: candidate: 'template<class PointerType, typename std::enable_if<std::is_pointer<_Tp>::value, int>::type <anonymous> > constexpr decltype (declval<const basic_json_t&>().get_ptr<PointerType>()) nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::get_impl(nlohmann::detail::priority_tag<4>) const [with PointerType = PointerType; typename std::enable_if<std::is_pointer<_Ptr>::value, int>::type <anonymous> = <anonymous>; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; BinaryType = std::vector<unsigned char>]'
20682 | constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
| ^~~~~~~~
json.hpp:20682:20: note: template argument deduction/substitution failed:
json.hpp:20681:25: error: no type named 'type' in 'struct std::enable_if<false, int>'
20681 | int> = 0>
| ^
json.hpp:20758:10: note: candidate: 'template<class PointerType, typename std::enable_if<std::is_pointer<_Tp>::value, int>::type <anonymous> > decltype (declval<nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::basic_json_t&>().get_ptr<PointerType>()) nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::get() [with PointerType = PointerType; typename std::enable_if<std::is_pointer<_Ptr>::value, int>::type <anonymous> = <anonymous>; ObjectType = std::map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long long int; NumberUnsignedType = long long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; BinaryType = std::vector<unsigned char>]'
20758 | auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
| ^~~
json.hpp:20758:10: note: template argument deduction/substitution failed:
json.hpp:20757:68: error: no type named 'type' in 'struct std::enable_if<false, int>'
20757 | std::is_pointer<PointerType>::value, int>::type = 0>
| ^
My questions:
- What are the error messages actually saying?
- How can this be fixed?