Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ambiguous conversion from nlohmann::basic_json<> to custom class. #3333

Closed
merzlya opened this issue Feb 15, 2022 · 3 comments · Fixed by #3629
Closed

Ambiguous conversion from nlohmann::basic_json<> to custom class. #3333

merzlya opened this issue Feb 15, 2022 · 3 comments · Fixed by #3629
Assignees
Labels
kind: bug release item: 🐛 bug fix solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@merzlya
Copy link

merzlya commented Feb 15, 2022

Compile time error occurs if I try to convert instance of nlohmann::basic_json<> to instance of class which has converting constructor with template specialization for nlohmann::basic_json<>. This regression is present in v3.10.4, v3.10.5 and develop (d8a6329).

Code example, which expose this issue - nlohmann-json-issue.cpp:

#include <iostream>
#include <stdexcept>
#include <nlohmann/json.hpp>

class Point final
{
public:
    Point(int x = 0, int y = 0, int z = 0);

    template <class T>
    Point(const T&);

    void Print() const;

    int x;
    int y;
    int z;
};

template <>
Point::Point(const nlohmann::json& json):
   Point(json.value("x", 0), json.value("y", 0), json.value("z", 0)) 
{
}

int main(void)
{
    const nlohmann::json pointJson = {
        {"x",111},
        {"y",222},
        {"z",333}
    };

    Point p = pointJson; // <- ambiguous conversion !!!
    p.Print();

    return 0;
}

Point::Point(int x, int y, int z): x(x), y(y), z(z)
{
}

template <class T>
Point::Point(const T&)
{
    throw std::logic_error("Not implemented");
}

void Point::Print() const
{
   std::cout << "(" << x << "," << y << "," << z << ")" << std::endl;
}

Compile error:

[pavel@well cpp-test]$ g++ nlohmann-json-issue.cpp -o nlohmann-json-issue
nlohmann-json-issue.cpp: In function ‘int main()’:
nlohmann-json-issue.cpp:33:15: error: conversion from ‘const json’ {aka ‘const nlohmann::basic_json<>’} to ‘Point’ is ambiguous
   33 |     Point p = pointJson; // <- ambiguous conversion !!!
      |               ^~~~~~~~~
In file included from nlohmann-json-issue.cpp:2:
/usr/include/nlohmann/json.hpp:1885:55: note: candidate: ‘nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>::operator ValueType() const [with ValueType = Point; typename std::enable_if<nlohmann::detail::conjunction<nlohmann::detail::negation<std::is_pointer<_Ptr> >, nlohmann::detail::negation<std::is_same<ValueType, nlohmann::detail::json_ref<nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType> > > >, nlohmann::detail::negation<std::is_same<ValueType, typename StringType::value_type> >, nlohmann::detail::negation<nlohmann::detail::is_basic_json<BasicJsonType> >, nlohmann::detail::negation<std::is_same<ValueType, std::initializer_list<typename StringType::value_type> > >, nlohmann::detail::negation<std::is_same<ValueType, std::basic_string_view<char, std::char_traits<char> > > >, nlohmann::detail::is_detected_lazy<nlohmann::detail::get_template_function, const nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType, AllocatorType, JSONSerializer, BinaryType>&, ValueType> >::value, int>::type <anonymous> = 0; ObjectType = std::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>]’
 1885 |                                         JSON_EXPLICIT operator ValueType() const
      |                                                       ^~~~~~~~
nlohmann-json-issue.cpp:20:1: note: candidate: ‘Point::Point(const T&) [with T = nlohmann::basic_json<>]’
   20 | Point::Point(const nlohmann::json& json):
      | ^~~~~

Workarounds:

  • compile with -DJSON_USE_IMPLICIT_CONVERSIONS=0;
  • make variable pointJson mutable;

Compiler: g++ (GCC) 11.1.0
OS: Arch Linux

@nlohmann
Copy link
Owner

You mention a regression - in which version of the library did your code work before?

@merzlya
Copy link
Author

merzlya commented Feb 15, 2022

In v3.6.1 everything was fine.
Just checked and following versions also are ok:

  • v3.10.3
  • v3.10.2
  • v3.10.0
  • v3.9.1
  • v3.9.0
  • v3.8.0
  • v3.7.0
  • v3.6.0
  • v3.5.0
  • v3.4.0
  • v3.3.0

@falbrechtskirchinger
Copy link
Contributor

@nlohmann This issue was fixed by #3604.

falbrechtskirchinger added a commit to falbrechtskirchinger/json that referenced this issue Jul 30, 2022
falbrechtskirchinger added a commit to falbrechtskirchinger/json that referenced this issue Jul 30, 2022
falbrechtskirchinger added a commit to falbrechtskirchinger/json that referenced this issue Jul 30, 2022
@nlohmann nlohmann self-assigned this Jul 30, 2022
@nlohmann nlohmann added solution: proposed fix a fix for the issue has been proposed and waits for confirmation release item: 🐛 bug fix labels Jul 30, 2022
@nlohmann nlohmann added this to the Release 3.11.0 milestone Jul 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug release item: 🐛 bug fix solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants