nlohmann / json

JSON for Modern C++
https://json.nlohmann.me
MIT License
41.46k stars 6.59k forks source link

Clang++ compilation fails on extremely small example #4061

Closed perlippens closed 9 months ago

perlippens commented 1 year ago

Description

The small example compiles with g++ but not with clang++-9.0.1/gcc-9.2.0 or later

The compile error is caused by the operator== declaration for unrelated class A objects where class A is forward declared. Not sure whether this is a clang issue or a json issue.

Reproduction steps

Compile the minimal code example using clang++ version 9.0.1 or later

Expected vs. actual results

Expecting no compile errors.

Minimal code example

#include <json.hpp>

using json = nlohmann::json;

class A; // fwd declaration
bool operator==(const A& c1, const A& c2);

bool test()
{
  json json;
  return json["key"] == "value";
}

Error messages

In file included from t.cc:1:
In file included from ./json.hpp:21:
In file included from /depot/gcc-9.2.0/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0/algorithm:60:
In file included from /depot/gcc-9.2.0/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0/utility:70:
In file included from /depot/gcc-9.2.0/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0/bits/stl_pair.h:59:
In file included from /depot/gcc-9.2.0/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0/bits/move.h:55:
/depot/gcc-9.2.0/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0/type_traits:884:32: error: incomplete type 'A' used in type trait expression
      : public __bool_constant<__is_constructible(_Tp, _Args...)>
                               ^
/depot/gcc-9.2.0/lib/gcc/x86_64-redhat-linux/9.2.0/../../../../include/c++/9.2.0/type_traits:890:14: note: in instantiation of template class 'std::is_constructible<A>' requested here
    : public is_constructible<_Tp>::type
             ^
./json.hpp:3602:35: note: in instantiation of template class 'std::is_default_constructible<A>' requested here
struct is_default_constructible : std::is_default_constructible<T> {};
                                  ^
./json.hpp:20819:28: note: in instantiation of template class 'nlohmann::json_abi_v3_11_2::detail::is_default_constructible<A>' requested here
                   detail::is_default_constructible<ValueType>::value&&
                           ^
./json.hpp:20822:15: note: while substituting prior template arguments into non-type template parameter [with ValueType = A]
    ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./json.hpp:20962:62: note: while substituting deduced template arguments into function template 'get_impl' [with ValueType = A, $1 = (no value)]
    -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
                                                             ^
./json.hpp:3509:67: note: (skipping 10 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
using get_template_function = decltype(std::declval<T>().template get<U>());
                                                                  ^
./json.hpp:3593:3: note: in instantiation of template class 'nlohmann::json_abi_v3_11_2::detail::conjunction<nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, nlohmann::json_abi_v3_11_2::detail::json_ref<nlohmann::json_abi_v3_11_2::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> > > >, nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, char> >, nlohmann::json_abi_v3_11_2::detail::negation<nlohmann::json_abi_v3_11_2::detail::is_basic_json<A> >, nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, std::initializer_list<char> > >, nlohmann::json_abi_v3_11_2::detail::is_detected_lazy<detail::get_template_function, const nlohmann::json_abi_v3_11_2::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> &, A> >' requested here
: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
  ^
./json.hpp:3593:3: note: in instantiation of template class 'nlohmann::json_abi_v3_11_2::detail::conjunction<nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, nullptr_t> >, nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, nlohmann::json_abi_v3_11_2::detail::json_ref<nlohmann::json_abi_v3_11_2::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> > > >, nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, char> >, nlohmann::json_abi_v3_11_2::detail::negation<nlohmann::json_abi_v3_11_2::detail::is_basic_json<A> >, nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, std::initializer_list<char> > >, nlohmann::json_abi_v3_11_2::detail::is_detected_lazy<detail::get_template_function, const nlohmann::json_abi_v3_11_2::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> &, A> >' requested here
./json.hpp:21097:28: note: in instantiation of template class 'nlohmann::json_abi_v3_11_2::detail::conjunction<nlohmann::json_abi_v3_11_2::detail::negation<std::is_pointer<A> >, nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, nullptr_t> >, nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, nlohmann::json_abi_v3_11_2::detail::json_ref<nlohmann::json_abi_v3_11_2::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> > > >, nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, char> >, nlohmann::json_abi_v3_11_2::detail::negation<nlohmann::json_abi_v3_11_2::detail::is_basic_json<A> >, nlohmann::json_abi_v3_11_2::detail::negation<std::is_same<A, std::initializer_list<char> > >, nlohmann::json_abi_v3_11_2::detail::is_detected_lazy<detail::get_template_function, const nlohmann::json_abi_v3_11_2::basic_json<std::map, std::vector, std::__cxx11::basic_string<char>, bool, long, unsigned long, double, std::allocator, adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void> &, A> >' requested here
                   detail::conjunction <
                           ^
./json.hpp:21112:55: note: while substituting prior template arguments into non-type template parameter [with ValueType = A]
                                        JSON_EXPLICIT operator ValueType() const
                                                      ^~~~~~~~~~~~~~~~~~~~~~~~~~
t.cc:11:10: note: while substituting deduced template arguments into function template 'operator type-parameter-0-0' [with ValueType = A, $1 = (no value)]
  return json["key"] == "value";
         ^
t.cc:5:7: note: forward declaration of 'A'
class A; // fwd declaration
      ^

Compiler and operating system

clang++-9.0.1 (clang901_gcc920)

Library version

3.11.2 (single header)

Validation

ryc111 commented 1 year ago

json json;

How can you expect this code to be compiled?

just like

int int;

gregmarr commented 10 months ago

The json json; code is technically valid, though I would say bad style. int int; won't compile because int is a reserved keyword.