Skip to content

Parse to custom class from unordered_json breaks on G++11.2.0 with C++20 #3312

Closed
@NeroBurner

Description

@NeroBurner

What is the issue you have?

Parsing a custom class with a std::string member in it using nlohmann::ordered_json with C++20 starting with v3.10.4 results in a compilation error.

Using v3.10.3 compiles fine

Probably related issue: #3207

Please describe the steps to reproduce the issue.

Godbolt link with example showing that g++ 11.2.0 fails to compile when C++20 is enabled

https://godbolt.org/z/MsYe45qP9

  1. Add custom class containing a std::string (custom class with just an int works)
  2. Add custom from_json function for custom class
  3. convert from ordered_json to class (normal unordered json works)
  4. get compilation error

Example code, which I'd like to add to unittests, but don't know where. (for the error message I added it to the bottom of unit-deserialization.cpp)

struct MyClass {
    std::string name;
};

void from_json(const nlohmann::json &j, MyClass &obj)
{
    j.at("name").get_to(obj.name);
}

TEST_CASE("custom class parsing")
{
    SECTION("parse class directly")
    {
        nlohmann::ordered_json j = nlohmann::ordered_json::parse("{\"name\": \"class\"}");
        MyClass obj;
        j.get_to(obj);
        CHECK(obj.name == "class");
    }
}

Can you provide a small but working code example?

see above

What is the expected behavior?

Compile without error

And what is the actual behavior instead?

Compillation error:

In file included from /home/nero/repos/external/nlohmann-json/test/src/unit-deserialization.cpp:32:
/home/nero/repos/external/nlohmann-json/single_include/nlohmann/json.hpp: In instantiation of 'void nlohmann::detail::from_json(const BasicJsonType&, ConstructibleStringType&) [with BasicJsonType = nlohmann::basic_json<nlohmann::ordered_map>; ConstructibleStringType = MyClass; typename std::enable_if<(nlohmann::detail::is_constructible_string_type<BasicJsonType, ConstructibleStringType>::value && (! std::is_same<typename BasicJsonType::string_t, ConstructibleStringType>::value)), int>::type <anonymous> = 0]':
/home/nero/repos/external/nlohmann-json/single_include/nlohmann/json.hpp:4273:25:   required from 'decltype (nlohmann::detail::from_json(j, forward<T>(val))) nlohmann::detail::from_json_fn::operator()(const BasicJsonType&, T&&) const [with BasicJsonType = nlohmann::basic_json<nlohmann::ordered_map>; T = MyClass&; decltype (nlohmann::detail::from_json(j, forward<T>(val))) = void]'
/home/nero/repos/external/nlohmann-json/single_include/nlohmann/json.hpp:4934:30:   required from 'static decltype ((nlohmann::{anonymous}::from_json(forward<BasicJsonType>(j), val), void())) nlohmann::adl_serializer<T, SFINAE>::from_json(BasicJsonType&&, TargetType&) [with BasicJsonType = const nlohmann::basic_json<nlohmann::ordered_map>&; TargetType = MyClass; ValueType = MyClass; <template-parameter-1-2> = void; decltype ((nlohmann::{anonymous}::from_json(forward<BasicJsonType>(j), val), void())) = void]'
/home/nero/repos/external/nlohmann-json/single_include/nlohmann/json.hpp:18955:45:   required from 'ValueType& nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::get_to(ValueType&) const [with ValueType = MyClass; typename std::enable_if<((! nlohmann::detail::is_basic_json<BasicJsonType>::value) && nlohmann::detail::has_from_json<nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>, ValueType>::value), int>::type <anonymous> = 0; ObjectType = nlohmann::ordered_map; ArrayType = std::vector; StringType = std::__cxx11::basic_string<char>; BooleanType = bool; NumberIntegerType = long int; NumberUnsignedType = long unsigned int; NumberFloatType = double; AllocatorType = std::allocator; JSONSerializer = nlohmann::adl_serializer; BinaryType = std::vector<unsigned char>]'
/home/nero/repos/external/nlohmann-json/test/src/unit-deserialization.cpp:1143:17:   required from here
/home/nero/repos/external/nlohmann-json/single_include/nlohmann/json.hpp:3914:7: error: no match for 'operator=' (operand types are 'MyClass' and 'const string_t' {aka 'const std::__cxx11::basic_string<char>'})
 3914 |     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
      |     ~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/nero/repos/external/nlohmann-json/test/src/unit-deserialization.cpp:1127:8: note: candidate: 'MyClass& MyClass::operator=(const MyClass&)'
 1127 | struct MyClass {
      |        ^~~~~~~
/home/nero/repos/external/nlohmann-json/test/src/unit-deserialization.cpp:1127:8: note:   no known conversion for argument 1 from 'const string_t' {aka 'const std::__cxx11::basic_string<char>'} to 'const MyClass&'
/home/nero/repos/external/nlohmann-json/test/src/unit-deserialization.cpp:1127:8: note: candidate: 'MyClass& MyClass::operator=(MyClass&&)'
/home/nero/repos/external/nlohmann-json/test/src/unit-deserialization.cpp:1127:8: note:   no known conversion for argument 1 from 'const string_t' {aka 'const std::__cxx11::basic_string<char>'} to 'MyClass&&'

Error message when compiling with Visual Studio 16 2019 in C++20 mode:

Error    C2679    binary '=': no operator found which takes a right-hand operand of type 'const std::basic_string<char,std::char_traits<char>,std::allocator<char>>' (or there is no acceptable conversion)    test    C:\Software\vcpkg\installed\x64-windows\include\nlohmann\detail\conversions\from_json.hpp    121

Which compiler and operating system are you using?

  • Compiler: g++ 11.2.0 (only when setting C++20 mode)
  • Operating system: Ubuntu 21.10

Also on Visual Studio 16 2019 in C++20 mode

Which version of the library did you use?

  • latest release version 3.10.5
  • other release: 3.10.4
  • other release: 3.10.3 (not affected by bug, working)
  • the develop branch

If you experience a compilation error: can you compile and run the unit tests?

  • yes
  • no - please copy/paste the error message below
"test-comparison" start time: Feb 01 15:05 UTC
Output:
----------------------------------------------------------
[doctest] doctest version is "2.4.6"
[doctest] run with "--help" for options
===============================================================================
/home/nero/repos/external/nlohmann-json/test/src/unit-comparison.cpp:46:
TEST CASE:  lexicographical comparison operators
  values
  comparison: less

/home/nero/repos/external/nlohmann-json/test/src/unit-comparison.cpp:213: ERROR: CHECK( (j_values[i] < j_values[j]) == expected[i][j] ) is NOT correct!
  values: CHECK( false == 1 )
  logged: i := 12
          j := 13
          j_values[i] := [1,2,3]
          j_values[j] := ["one","two","three"]

/home/nero/repos/external/nlohmann-json/test/src/unit-comparison.cpp:213: ERROR: CHECK( (j_values[i] < j_values[j]) == expected[i][j] ) is NOT correct!
  values: CHECK( true == 0 )
  logged: i := 13
          j := 12
          j_values[i] := ["one","two","three"]
          j_values[j] := [1,2,3]

===============================================================================
[doctest] test cases:    1 |    0 passed | 1 failed | 0 skipped
[doctest] assertions: 2220 | 2218 passed | 2 failed |
[doctest] Status: FAILURE!

edit: the unittest test-comparison fails in C++20 mode, as reported in issue: #3207

Metadata

Metadata

Assignees

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions