diff --git a/include/nlohmann/detail/macro_scope.hpp b/include/nlohmann/detail/macro_scope.hpp index 23384982c..b8d2288d3 100644 --- a/include/nlohmann/detail/macro_scope.hpp +++ b/include/nlohmann/detail/macro_scope.hpp @@ -592,14 +592,20 @@ void templated_json_throw(ExceptionType exception) // (issue #4041, e.g. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type) with no further // arguments). NLOHMANN_JSON_TYPE_TAG(...) expands to the token 1 when // __VA_ARGS__ is a single token (Type alone) and to N for two or more (Type, -// member...); NLOHMANN_JSON_DERIVED_TYPE_TAG(...) is the same idea shifted by -// one slot for the two-token Type,BaseType prefix used by the derived-type -// macros. Both reuse the existing 64-slot NLOHMANN_JSON_GET_MACRO dispatch +// member...). It reuses the existing 64-slot NLOHMANN_JSON_GET_MACRO dispatch // with one extra trailing sentinel token appended so its own trailing "..." // is never left completely empty at the lowest supported argument count -- // invoking a variadic macro so that "..." matches nothing is only granted // unconditionally by the standard since C++20, and pre-C++20 compilers may // reject it under -pedantic regardless of what the macro body does. +// +// NLOHMANN_JSON_DERIVED_TYPE_TAG(...) answers the same question for the +// derived-type macros, whose fixed prefix is Type,BaseType. It drops the +// leading Type and defers to NLOHMANN_JSON_TYPE_TAG rather than shifting the +// slot table by one: NLOHMANN_JSON_GET_MACRO only resolves 64 positional +// arguments, so tagging Type,BaseType,member... directly would run out one +// slot early and cap the derived-type macros at 62 members instead of the 63 +// that NLOHMANN_JSON_PASTE supports. #define NLOHMANN_JSON_CAT_(x, y) x ## y #define NLOHMANN_JSON_CAT(x, y) NLOHMANN_JSON_CAT_(x, y) @@ -613,15 +619,8 @@ void templated_json_throw(ExceptionType exception) N, N, N, 1, \ NLOHMANN_JSON_TYPE_TAG_SENTINEL)) -#define NLOHMANN_JSON_DERIVED_TYPE_TAG(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, 2, N, \ - NLOHMANN_JSON_DERIVED_TYPE_TAG_SENTINEL)) +#define NLOHMANN_JSON_DERIVED_TYPE_TAG_(Type, ...) NLOHMANN_JSON_TYPE_TAG(__VA_ARGS__) +#define NLOHMANN_JSON_DERIVED_TYPE_TAG(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DERIVED_TYPE_TAG_(__VA_ARGS__)) /*! @brief macro @@ -751,7 +750,7 @@ void templated_json_throw(ExceptionType exception) NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend 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__)) }) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) \ /* NOLINTNEXTLINE(bugprone-macro-parentheses) Type/BaseType are used as declarator types, not in expressions */ \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) @@ -772,7 +771,7 @@ void templated_json_throw(ExceptionType exception) NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend 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__)) }) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) \ /* NOLINTNEXTLINE(bugprone-macro-parentheses) Type/BaseType are used as declarator types, not in expressions */ \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) @@ -792,7 +791,7 @@ void templated_json_throw(ExceptionType exception) #define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_N(Type, BaseType, ...) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend 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__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_CAT(NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_, NLOHMANN_JSON_DERIVED_TYPE_TAG(__VA_ARGS__))(__VA_ARGS__)) @@ -811,7 +810,7 @@ void templated_json_throw(ExceptionType exception) NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(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__)) }) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) \ /* NOLINTNEXTLINE(bugprone-macro-parentheses) Type/BaseType are used as declarator types, not in expressions */ \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) @@ -832,7 +831,7 @@ void templated_json_throw(ExceptionType exception) NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(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__)) }) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) \ /* NOLINTNEXTLINE(bugprone-macro-parentheses) Type/BaseType are used as declarator types, not in expressions */ \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) @@ -852,7 +851,7 @@ void templated_json_throw(ExceptionType exception) #define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_N(Type, BaseType, ...) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(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__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_CAT(NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_, NLOHMANN_JSON_DERIVED_TYPE_TAG(__VA_ARGS__))(__VA_ARGS__)) diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index 0db151a74..8d07197e0 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -2967,14 +2967,20 @@ void templated_json_throw(ExceptionType exception) // (issue #4041, e.g. NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type) with no further // arguments). NLOHMANN_JSON_TYPE_TAG(...) expands to the token 1 when // __VA_ARGS__ is a single token (Type alone) and to N for two or more (Type, -// member...); NLOHMANN_JSON_DERIVED_TYPE_TAG(...) is the same idea shifted by -// one slot for the two-token Type,BaseType prefix used by the derived-type -// macros. Both reuse the existing 64-slot NLOHMANN_JSON_GET_MACRO dispatch +// member...). It reuses the existing 64-slot NLOHMANN_JSON_GET_MACRO dispatch // with one extra trailing sentinel token appended so its own trailing "..." // is never left completely empty at the lowest supported argument count -- // invoking a variadic macro so that "..." matches nothing is only granted // unconditionally by the standard since C++20, and pre-C++20 compilers may // reject it under -pedantic regardless of what the macro body does. +// +// NLOHMANN_JSON_DERIVED_TYPE_TAG(...) answers the same question for the +// derived-type macros, whose fixed prefix is Type,BaseType. It drops the +// leading Type and defers to NLOHMANN_JSON_TYPE_TAG rather than shifting the +// slot table by one: NLOHMANN_JSON_GET_MACRO only resolves 64 positional +// arguments, so tagging Type,BaseType,member... directly would run out one +// slot early and cap the derived-type macros at 62 members instead of the 63 +// that NLOHMANN_JSON_PASTE supports. #define NLOHMANN_JSON_CAT_(x, y) x ## y #define NLOHMANN_JSON_CAT(x, y) NLOHMANN_JSON_CAT_(x, y) @@ -2988,15 +2994,8 @@ void templated_json_throw(ExceptionType exception) N, N, N, 1, \ NLOHMANN_JSON_TYPE_TAG_SENTINEL)) -#define NLOHMANN_JSON_DERIVED_TYPE_TAG(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, N, N, N, N, N, N, N, N, \ - N, N, 2, N, \ - NLOHMANN_JSON_DERIVED_TYPE_TAG_SENTINEL)) +#define NLOHMANN_JSON_DERIVED_TYPE_TAG_(Type, ...) NLOHMANN_JSON_TYPE_TAG(__VA_ARGS__) +#define NLOHMANN_JSON_DERIVED_TYPE_TAG(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_DERIVED_TYPE_TAG_(__VA_ARGS__)) /*! @brief macro @@ -3126,7 +3125,7 @@ void templated_json_throw(ExceptionType exception) NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend 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__)) }) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) \ /* NOLINTNEXTLINE(bugprone-macro-parentheses) Type/BaseType are used as declarator types, not in expressions */ \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) @@ -3147,7 +3146,7 @@ void templated_json_throw(ExceptionType exception) NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend 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__)) }) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) \ /* NOLINTNEXTLINE(bugprone-macro-parentheses) Type/BaseType are used as declarator types, not in expressions */ \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) @@ -3167,7 +3166,7 @@ void templated_json_throw(ExceptionType exception) #define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_N(Type, BaseType, ...) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend 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__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) #define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_CAT(NLOHMANN_JSON_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE_, NLOHMANN_JSON_DERIVED_TYPE_TAG(__VA_ARGS__))(__VA_ARGS__)) @@ -3186,7 +3185,7 @@ void templated_json_throw(ExceptionType exception) NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(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__)) }) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) \ /* NOLINTNEXTLINE(bugprone-macro-parentheses) Type/BaseType are used as declarator types, not in expressions */ \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) @@ -3207,7 +3206,7 @@ void templated_json_throw(ExceptionType exception) NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(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__)) }) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) \ /* NOLINTNEXTLINE(bugprone-macro-parentheses) Type/BaseType are used as declarator types, not in expressions */ \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) @@ -3227,7 +3226,7 @@ void templated_json_throw(ExceptionType exception) #define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_N(Type, BaseType, ...) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(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__)) }) -#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_2(Type, BaseType) \ +#define NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_1(Type, BaseType) \ NLOHMANN_JSON_BASIC_TYPE_TEMPLATE(void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast(nlohmann_json_t)); }) #define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_CAT(NLOHMANN_JSON_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE_, NLOHMANN_JSON_DERIVED_TYPE_TAG(__VA_ARGS__))(__VA_ARGS__)) diff --git a/tests/src/unit-udt_macro.cpp b/tests/src/unit-udt_macro.cpp index e03f6920e..aa25aa27c 100644 --- a/tests/src/unit-udt_macro.cpp +++ b/tests/src/unit-udt_macro.cpp @@ -896,6 +896,36 @@ class empty_derived_non_intrusive_only_serialize : public person_with_private_da // NOLINTNEXTLINE(misc-use-internal-linkage) NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(empty_derived_non_intrusive_only_serialize, person_with_private_data) +// Types at the documented maximum member count (63) for issue #4041's +// argument-count dispatch. The derived-type macros carry a two-token +// Type,BaseType prefix, so they reach two slots further into +// NLOHMANN_JSON_GET_MACRO than the non-derived ones and are the first to break +// if the tag dispatch runs out of positional slots. +class max_members +{ + public: + int m1{}, m2{}, m3{}, m4{}, m5{}, m6{}, m7{}, m8{}, m9{}, m10{}, m11{}, m12{}, m13{}, m14{}, m15{}, m16{}, m17{}, m18{}, m19{}, m20{}, m21{}, m22{}, m23{}, m24{}, m25{}, m26{}, m27{}, m28{}, m29{}, m30{}, m31{}, m32{}, m33{}, m34{}, m35{}, m36{}, m37{}, m38{}, m39{}, m40{}, m41{}, m42{}, m43{}, m44{}, m45{}, m46{}, m47{}, m48{}, m49{}, m50{}, m51{}, m52{}, m53{}, m54{}, m55{}, m56{}, m57{}, m58{}, m59{}, m60{}, m61{}, m62{}, m63{}; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(max_members, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53, m54, m55, m56, m57, m58, m59, m60, m61, m62, m63) +}; + +class max_members_base +{ + public: + int base_value = 0; + + NLOHMANN_DEFINE_TYPE_INTRUSIVE(max_members_base, base_value) +}; + +class max_members_derived : public max_members_base +{ + public: + int m1{}, m2{}, m3{}, m4{}, m5{}, m6{}, m7{}, m8{}, m9{}, m10{}, m11{}, m12{}, m13{}, m14{}, m15{}, m16{}, m17{}, m18{}, m19{}, m20{}, m21{}, m22{}, m23{}, m24{}, m25{}, m26{}, m27{}, m28{}, m29{}, m30{}, m31{}, m32{}, m33{}, m34{}, m35{}, m36{}, m37{}, m38{}, m39{}, m40{}, m41{}, m42{}, m43{}, m44{}, m45{}, m46{}, m47{}, m48{}, m49{}, m50{}, m51{}, m52{}, m53{}, m54{}, m55{}, m56{}, m57{}, m58{}, m59{}, m60{}, m61{}, m62{}, m63{}; + + NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(max_members_derived, max_members_base, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20, m21, m22, m23, m24, m25, m26, m27, m28, m29, m30, m31, m32, m33, m34, m35, m36, m37, m38, m39, m40, m41, m42, m43, m44, m45, m46, m47, m48, m49, m50, m51, m52, m53, m54, m55, m56, m57, m58, m59, m60, m61, m62, m63) +}; + + } // namespace persons TEST_CASE_TEMPLATE("Serialization/deserialization via NLOHMANN_DEFINE_TYPE_INTRUSIVE and NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE", Pair, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) @@ -1414,3 +1444,36 @@ TEST_CASE_TEMPLATE("Serialization/deserialization of zero-member types via NLOHM CHECK(j.dump() == derived_dump); } } + +// Regression test for the argument-count dispatch added for issue #4041: the +// documented maximum of 63 members must keep working, including for the +// derived-type macros whose Type,BaseType prefix consumes two dispatch slots. +TEST_CASE_TEMPLATE("Serialization/deserialization of maximum-member-count types via NLOHMANN_DEFINE_TYPE_*", Json, // NOLINT(readability-math-missing-parentheses, bugprone-throwing-static-initialization) + nlohmann::json, nlohmann::ordered_json) +{ + SECTION("NLOHMANN_DEFINE_TYPE_INTRUSIVE with 63 members") + { + persons::max_members obj{}; + obj.m1 = 1; + obj.m63 = 63; + Json j = obj; + CHECK(j.size() == 63); + const auto obj2 = j.template get(); + CHECK(obj2.m1 == 1); + CHECK(obj2.m63 == 63); + } + + SECTION("NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE with 63 own members") + { + persons::max_members_derived obj{}; + obj.base_value = 7; + obj.m1 = 1; + obj.m63 = 63; + Json j = obj; + CHECK(j.size() == 64); + const auto obj2 = j.template get(); + CHECK(obj2.base_value == 7); + CHECK(obj2.m1 == 1); + CHECK(obj2.m63 == 63); + } +}