Skip to content

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

Closed

Description

@merzlya

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

Activity

  1. nlohmann commented on Feb 15, 2022

    @nlohmann
    Owner

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

  2. merzlya commented on Feb 15, 2022

    @merzlya
    Author

    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
  3. falbrechtskirchinger commented on Jul 29, 2022

    @falbrechtskirchinger
    Contributor

    @nlohmann This issue was fixed by #3604.

  4. self-assigned this
    on Jul 30, 2022
  5. added this to the Release 3.11.0 milestone on Jul 30, 2022
  6. added a commit that references this issue on Jul 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    ⌂ 换网址