The code used to build with 3.10.2 but fails now
Description
I could convert nlohmann::json to a std::variant implicitly with version 3.10.2, but with the latest version, I can't.
With the latest version, the code doesn't build.
I don't know whether it is this way for a reason (I apologize if so), or a regression.
Reproduction steps
Try to build the given code.
Expected vs. actual results
The code used to build with v3.10.2, but it doesn't with the tip of develop branch.
Minimal code example
nlohmann::json test_json;
std::variant<size_t, std::string> val{test_json};
Error messages
error: no matching function for call to 'std::variant<unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::variant(<brace-enclosed initializer list>)'
[build] std::variant<size_t, std::string> val{test_json};
[build] ^
Compiler and operating system
Windows 10, GCC 8.3.0 for ARM
Library version
a3e6e26dc83a726b292f5be0492fcc408663ce55
Validation
- [X] The bug also occurs if the latest version from the
developbranch is used. - [X] I can successfully compile and run the unit tests.
Oh, I found this: https://github.com/nlohmann/json/issues/958 It's not recommended to use implicit conversions anyway. I'm sorry.
I'm sorry again, on the second thought you were going to remove the support for implicit conversions from JSON in the next major version, so I thought you might still like to look at this.
Okay, I tried to change the code to
nlohmann::json test_json;
std::variant<size_t, std::string> val = test_json.get<std::variant<size_t, std::string>>();
and I still get the error:
error: no matching function for call to 'nlohmann::json_abi_v3_11_2::basic_json<>::get<std::variant<unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >()'
[build] std::variant<size_t, std::string> val = test_json.get<std::variant<size_t, std::string>>();
[build] ^
It seems the explicit conversion is also broken.
Based on the discussion in #1261, it was never assumed it should work and worked only by chance?.. I need to explicitly add variant support, correct?.. On another hand, that issue is about serialization, whereas I was interested in deserialization only. So I don't know if it should work, or the operation was never guaranteed.
The breaking commit was a87c1885cb784ea5b884ed6dd1c96e39b7b4ec64.
I have to take a closer look to be sure, but here are my initial thoughts:
There's no built-in conversion for std::variant, meaning the compiler will look for any compatible conversion and won't find an unambiguous one.
I need to explicitly add variant support, correct?..
Yes, you need to provide your own to_json/from_json functions to implement the desired conversion behavior.
std::variant<size_t, std::string> val = test_json.get<std::variant<size_t, std::string>>();
This does not change the fact that there's no conversion available. The following lines should work instead:
std::variant<size_t, std::string> val = test_json.get<size_t>();
// or
std::variant<size_t, std::string> val = test_json.get<std::string>();
These calls can of course still fail at runtime, depending on the stored type.
I understand, but the thing is that the code did build and run and work correctly with 3.10.2. It's like it queried the stored type under the hood and called the correct nlohmann::json::get specialization.
It seems that it was a bug before to have supported an example with std::variant.
Did it break something? Because it is convenient, looks like a feature to me.