diff --git a/cmake/clang_flags.cmake b/cmake/clang_flags.cmake index b3dfa31440..09ec07d3c3 100644 --- a/cmake/clang_flags.cmake +++ b/cmake/clang_flags.cmake @@ -19,4 +19,5 @@ set(CLANG_CXXFLAGS -Wno-covered-switch-default -Wno-unsafe-buffer-usage -Wno-missing-noreturn + -Wno-gnu-zero-variadic-macro-arguments ) diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index afb400c90b..ec741a6b9e 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -544,6 +544,28 @@ template::value, int> = 0> \ void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } +/*! +@brief macro +@def NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE +@since version 3.12.0 +*/ +#define NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE(Type) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type&) { nlohmann_json_j = BasicJsonType::object(); } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType&, Type&) noexcept { } + +/*! +@brief macro +@def NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE +@since version 3.12.0 +*/ +#define NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE(Type) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type&) { nlohmann_json_j = BasicJsonType::object(); } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType&, Type&) noexcept { } + // inspired from https://stackoverflow.com/a/26745591 // allows calling any std function as if (e.g., with begin): // using std::begin; begin(x); diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index e2bb8517b6..0beae83832 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2908,6 +2908,28 @@ JSON_HEDLEY_DIAGNOSTIC_POP template::value, int> = 0> \ void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } +/*! +@brief macro +@def NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE +@since version 3.12.0 +*/ +#define NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE(Type) \ + template::value, int> = 0> \ + friend void to_json(BasicJsonType& nlohmann_json_j, const Type&) { nlohmann_json_j = BasicJsonType::object(); } \ + template::value, int> = 0> \ + friend void from_json(const BasicJsonType&, Type&) noexcept { } + +/*! +@brief macro +@def NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE +@since version 3.12.0 +*/ +#define NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE(Type) \ + template::value, int> = 0> \ + void to_json(BasicJsonType& nlohmann_json_j, const Type&) { nlohmann_json_j = BasicJsonType::object(); } \ + template::value, int> = 0> \ + void from_json(const BasicJsonType&, Type&) noexcept { } + // inspired from https://stackoverflow.com/a/26745591 // allows calling any std function as if (e.g., with begin): // using std::begin; begin(x); diff --git a/tests/src/unit-udt_macro.cpp b/tests/src/unit-udt_macro.cpp index cd65134297..18a4df3c16 100644 --- a/tests/src/unit-udt_macro.cpp +++ b/tests/src/unit-udt_macro.cpp @@ -707,3 +707,36 @@ TEST_CASE_TEMPLATE("Serialization of non-default-constructible classes via NLOHM R"([{"age":1,"hair_color":"brown","name":"Erik"},{"age":2,"hair_color":"black","name":"Kyle"}])")); } } + +namespace emptys +{ +class empty_intrusive +{ + NLOHMANN_DEFINE_EMPTY_TYPE_INTRUSIVE(empty_intrusive) +}; + +class empty_non_intrusive +{ +}; + +NLOHMANN_DEFINE_EMPTY_TYPE_NON_INTRUSIVE(empty_non_intrusive) + +} // namespace emptys + +TEST_CASE_TEMPLATE("Serialization/deserialization of classes with no member variables", T, + emptys::empty_intrusive, + emptys::empty_non_intrusive) +{ + SECTION("empty") + { + { + T empty; + std::string const s = json(empty).dump(); + CHECK(s == "{}"); + + nlohmann::json const json_empty = nlohmann::json::parse(s); + T empty2; + json_empty.get_to(empty2); + } + } +}