diff --git a/README.md b/README.md index 21ff833b..31e12ca9 100644 --- a/README.md +++ b/README.md @@ -956,7 +956,7 @@ The library itself contains of a single header file licensed under the MIT licen - [**Doxygen**](http://www.stack.nl/~dimitri/doxygen/) to generate [documentation](https://nlohmann.github.io/json/) - [**git-update-ghpages**](https://github.com/rstacruz/git-update-ghpages) to upload the documentation to gh-pages - [**GitHub Changelog Generator**](https://github.com/skywinder/github-changelog-generator) to generate the [ChangeLog](https://github.com/nlohmann/json/blob/develop/ChangeLog.md) -- [**Google Benchmark**]https://github.com/google/benchmark) to implement the benchmarks +- [**Google Benchmark**](https://github.com/google/benchmark) to implement the benchmarks - [**libFuzzer**](http://llvm.org/docs/LibFuzzer.html) to implement fuzz testing for OSS-Fuzz - [**OSS-Fuzz**](https://github.com/google/oss-fuzz) for continuous fuzz testing of the library - [**Probot**](https://probot.github.io) for automating maintainer tasks such as closing stale issues, requesting missing information, or detecting toxic comments. diff --git a/develop/detail/meta.hpp b/develop/detail/meta.hpp index bea42a07..585b8d44 100644 --- a/develop/detail/meta.hpp +++ b/develop/detail/meta.hpp @@ -96,6 +96,14 @@ template<> struct priority_tag<0> {}; // has_/is_ functions // //////////////////////// +// source: https://stackoverflow.com/a/37193089/4116453 + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + NLOHMANN_JSON_HAS_HELPER(mapped_type); NLOHMANN_JSON_HAS_HELPER(key_type); NLOHMANN_JSON_HAS_HELPER(value_type); @@ -171,7 +179,6 @@ struct is_compatible_integer_type RealIntegerType, CompatibleNumberIntegerType > ::value; }; - // trait checking if JSONSerializer::from_json(json const&, udt&) exists template struct has_from_json @@ -221,6 +228,23 @@ struct has_to_json std::declval>()))>::value; }; +template +struct is_compatible_complete_type +{ + static constexpr bool value = + not std::is_base_of::value and + not std::is_same::value and + not is_basic_json_nested_type::value and + has_to_json::value; +}; + +template +struct is_compatible_type + : conjunction, + is_compatible_complete_type> +{ +}; + // taken from ranges-v3 template struct static_const diff --git a/develop/json.hpp b/develop/json.hpp index 56cc6f1a..467cea97 100644 --- a/develop/json.hpp +++ b/develop/json.hpp @@ -1551,15 +1551,13 @@ class basic_json @since version 2.1.0 */ - template, - detail::enable_if_t::value and - not std::is_same::value and - not detail::is_basic_json_nested_type< - basic_json_t, U>::value and - detail::has_to_json::value, - int> = 0> - basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer::to_json( - std::declval(), std::forward(val)))) + template , + detail::enable_if_t< + detail::is_compatible_type::value, int> = 0> + basic_json(CompatibleType && val) noexcept(noexcept( + JSONSerializer::to_json(std::declval(), + std::forward(val)))) { JSONSerializer::to_json(*this, std::forward(val)); assert_invariant(); diff --git a/src/json.hpp b/src/json.hpp index 409d3894..4c02b076 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -310,6 +310,14 @@ template<> struct priority_tag<0> {}; // has_/is_ functions // //////////////////////// +// source: https://stackoverflow.com/a/37193089/4116453 + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + NLOHMANN_JSON_HAS_HELPER(mapped_type); NLOHMANN_JSON_HAS_HELPER(key_type); NLOHMANN_JSON_HAS_HELPER(value_type); @@ -385,7 +393,6 @@ struct is_compatible_integer_type RealIntegerType, CompatibleNumberIntegerType > ::value; }; - // trait checking if JSONSerializer::from_json(json const&, udt&) exists template struct has_from_json @@ -435,6 +442,23 @@ struct has_to_json std::declval>()))>::value; }; +template +struct is_compatible_complete_type +{ + static constexpr bool value = + not std::is_base_of::value and + not std::is_same::value and + not is_basic_json_nested_type::value and + has_to_json::value; +}; + +template +struct is_compatible_type + : conjunction, + is_compatible_complete_type> +{ +}; + // taken from ranges-v3 template struct static_const @@ -10380,15 +10404,13 @@ class basic_json @since version 2.1.0 */ - template, - detail::enable_if_t::value and - not std::is_same::value and - not detail::is_basic_json_nested_type< - basic_json_t, U>::value and - detail::has_to_json::value, - int> = 0> - basic_json(CompatibleType && val) noexcept(noexcept(JSONSerializer::to_json( - std::declval(), std::forward(val)))) + template , + detail::enable_if_t< + detail::is_compatible_type::value, int> = 0> + basic_json(CompatibleType && val) noexcept(noexcept( + JSONSerializer::to_json(std::declval(), + std::forward(val)))) { JSONSerializer::to_json(*this, std::forward(val)); assert_invariant(); diff --git a/test/src/unit-udt.cpp b/test/src/unit-udt.cpp index 4fd6f7ec..a4adc3be 100644 --- a/test/src/unit-udt.cpp +++ b/test/src/unit-udt.cpp @@ -692,3 +692,22 @@ TEST_CASE("custom serializer that does adl by default", "[udt]") CHECK(me == j.get()); CHECK(me == cj.get()); } + +namespace +{ +struct incomplete; + +// std::is_constructible is broken on macOS' libc++ +// use the cppreference implementation + +template +struct is_constructible_patched : std::false_type {}; + +template +struct is_constructible_patched())))> : std::true_type {}; +} + +TEST_CASE("an incomplete type does not trigger a compiler error in non-evaluated context", "[udt]") +{ + static_assert(not is_constructible_patched::value, ""); +}