nlohmann / nlohmann/json

invalid use of incomplete type (boost::optional) / compile error

Open
#3,669 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

kind: bug
Dominant language
C++
Stars
50.6k
Forks
7.5k
Avg merge
4d 17h
Merged PRs (30d)
58

Description

Description

Hi there,

I get some compiler errors, which I unfortunately don't understand in detail. See the small minimal example. Probably it's a compiler bug, because it compiles with gcc 11+ and clang11. It also compiles with gcc 10 when using -std=c++17.

The code also compiles fine, if I comment out the "to_json" function or make the Dummy constructor non-explicit. I don't understand why in the gcc10 setup with c++11 standard, the to_json function gets inspected at all. How can it matter if this function exists or not?

Thank you for your comments!

Reproduction steps

See also https://godbolt.org/z/1Whjn8nKn

Expected vs. actual results

It should compile, but it doesn't.

Minimal code example
#include <boost/optional.hpp>

#include <nlohmann/json.hpp>

class Dummy {
    explicit Dummy(const nlohmann::json& data) {
    }
};

class Holder {
    boost::optional<Dummy> d;

public:
};

void to_json(nlohmann::json& j, const Holder& h) {
}

int main(int argc, char* argv[]) {
    Holder h;
    return 0;
}
Error messages
In file included from <source>:3:
/opt/compiler-explorer/libs/nlohmann_json/v3.6.0/single_include/nlohmann/json.hpp: In substitution of 'template<class Expected, template<class ...> class Op, class ... Args> using is_detected_exact = std::is_same<Expected, typename nlohmann::detail::detector<nlohmann::detail::nonesuch, void, Op, Args ...>::type> [with Expected = void; Op = nlohmann::detail::to_json_function; Args = {nlohmann::adl_serializer<Dummy, void>, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long int, long unsigned int, double, std::allocator, nlohmann::adl_serializer>&, Dummy}]':
/opt/compiler-explorer/libs/nlohmann_json/v3.6.0/single_include/nlohmann/json.hpp:986:13:   required from 'constexpr const bool nlohmann::detail::has_to_json<nlohmann::basic_json<>, Dummy, void>::value'
/opt/compiler-explorer/libs/nlohmann_json/v3.6.0/single_include/nlohmann/json.hpp:1204:53:   required from 'constexpr const bool nlohmann::detail::is_compatible_type_impl<nlohmann::basic_json<>, Dummy, void>::value'
/opt/compiler-explorer/libs/nlohmann_json/v3.6.0/single_include/nlohmann/json.hpp:14016:55:   required by substitution of 'template<class CompatibleType, class U, typename std::enable_if<((! nlohmann::detail::is_basic_json<T>::value) && nlohmann::detail::is_compatible_type<nlohmann::basic_json<>, U>::value), int>::type <anonymous> > nlohmann::basic_json<>::basic_json(CompatibleType&&) [with CompatibleType = Dummy; U = Dummy; typename std::enable_if<((! nlohmann::detail::is_basic_json<T>::value) && nlohmann::detail::is_compatible_type<nlohmann::basic_json<>, U>::value), int>::type <anonymous> = <missing>]'
/opt/compiler-explorer/libs/boost_1_79_0/boost/type_traits/is_constructible.hpp:37:65:   required by substitution of 'template<class T, class Arg, class> static boost::type_traits::yes_type boost::detail::is_constructible_imp::test1(int) [with T = Dummy; Arg = Dummy; <template-parameter-1-3> = <missing>]'
/opt/compiler-explorer/libs/boost_1_79_0/boost/type_traits/is_constructible.hpp:54:185:   required from 'struct boost::is_constructible<Dummy, Dummy>'
/opt/compiler-explorer/libs/boost_1_79_0/boost/optional/optional.hpp:816:8:   [ skipping 10 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/opt/compiler-explorer/libs/nlohmann_json/v3.6.0/single_include/nlohmann/json.hpp:14016:55:   required by substitution of 'template<class CompatibleType, class U, typename std::enable_if<((! nlohmann::detail::is_basic_json<T>::value) && nlohmann::detail::is_compatible_type<nlohmann::basic_json<>, U>::value), int>::type <anonymous> > nlohmann::basic_json<>::basic_json(CompatibleType&&) [with CompatibleType = const Dummy&; U = Dummy; typename std::enable_if<((! nlohmann::detail::is_basic_json<T>::value) && nlohmann::detail::is_compatible_type<nlohmann::basic_json<>, U>::value), int>::type <anonymous> = <missing>]'
/opt/compiler-explorer/libs/boost_1_79_0/boost/type_traits/is_constructible.hpp:37:65:   required by substitution of 'template<class T, class Arg, class> static boost::type_traits::yes_type boost::detail::is_constructible_imp::test1(int) [with T = Dummy; Arg = const Dummy&; <template-parameter-1-3> = <missing>]'
/opt/compiler-explorer/libs/boost_1_79_0/boost/type_traits/is_constructible.hpp:54:185:   required from 'struct boost::is_constructible<Dummy, const Dummy&>'
/opt/compiler-explorer/libs/boost_1_79_0/boost/optional/optional.hpp:816:8:   required from 'struct boost::optional_detail::is_optional_constructible<Dummy, const Dummy&>'
/opt/compiler-explorer/libs/boost_1_79_0/boost/core/enable_if.hpp:41:10:   required from 'struct boost::enable_if<boost::optional_detail::is_optional_constructible<Dummy, const Dummy&>, bool>'
/opt/compiler-explorer/libs/boost_1_79_0/boost/optional/optional.hpp:964:14:   required by substitution of 'template<class U> boost::optional<Dummy>::optional(const boost::optional<T>&, typename boost::enable_if<boost::optional_detail::is_optional_constructible<Dummy, const U&>, bool>::type) [with U = Dummy]'
<source>:20:12:   required from here
/opt/compiler-explorer/libs/nlohmann_json/v3.6.0/single_include/nlohmann/json.hpp:802:7: error: invalid use of incomplete type 'struct nlohmann::detail::detector<nlohmann::detail::nonesuch, void, nlohmann::detail::to_json_function, nlohmann::adl_serializer<Dummy, void>, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long int, long unsigned int, double, std::allocator, nlohmann::adl_serializer>&, Dummy>'
  802 | using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
      |       ^~~~~~~~~~~~~~~~~
/opt/compiler-explorer/libs/nlohmann_json/v3.6.0/single_include/nlohmann/json.hpp:776:8: note: declaration of 'struct nlohmann::detail::detector<nlohmann::detail::nonesuch, void, nlohmann::detail::to_json_function, nlohmann::adl_serializer<Dummy, void>, nlohmann::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long int, long unsigned int, double, std::allocator, nlohmann::adl_serializer>&, Dummy>'
  776 | struct detector
      |        ^~~~~~~~
Compiler returned: 1
Compiler and operating system

gcc 10, linux,

Library version

3.10.3

Validation

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the minimal example from the issue with GCC 10 in C++11, using boost::optional and nlohmann/json.hpp, then compare it with GCC 11+, Clang 11, and C++17. Use the Compiler Explorer example and the reported template-instantiation trace to identify why to_json triggers the incomplete-type error; done means the example compiles without requiring a non-explicit Dummy constructor.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.