Closed
Description
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