From f80e4e8038d20047c5eee236ad033f4cfb368a9f Mon Sep 17 00:00:00 2001 From: "Zezheng.Li" Date: Mon, 18 Mar 2024 15:21:47 +0800 Subject: [PATCH] [struct_pack] fixed serialize std::unique_ptr with T is derived class. --- include/ylt/struct_pack/derived_helper.hpp | 3 ++ include/ylt/struct_pack/derived_marco.hpp | 5 +- src/struct_pack/tests/test_derived.cpp | 53 +++++++++++++++++++++- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/include/ylt/struct_pack/derived_helper.hpp b/include/ylt/struct_pack/derived_helper.hpp index 8a78f06f9..2ac6d33f3 100644 --- a/include/ylt/struct_pack/derived_helper.hpp +++ b/include/ylt/struct_pack/derived_helper.hpp @@ -168,6 +168,9 @@ struct deserialize_one_derived_class_helper { } }; +template +void struct_pack_derived_decl(const T *) = delete; + template using derived_class_set_t = decltype(struct_pack_derived_decl((Base *)nullptr)); diff --git a/include/ylt/struct_pack/derived_marco.hpp b/include/ylt/struct_pack/derived_marco.hpp index af50399f3..8e193ef4b 100644 --- a/include/ylt/struct_pack/derived_marco.hpp +++ b/include/ylt/struct_pack/derived_marco.hpp @@ -14,9 +14,8 @@ * limitations under the License. */ -#include "foreach_macro.h" - #pragma once +#include "foreach_macro.h" #define GET_STRUCT_PACK_ID_IMPL_FOR_LOOP(idx, type) \ inline uint32_t type::get_struct_pack_id() const { \ @@ -26,7 +25,7 @@ #define STRUCT_PACK_DERIVED_DECL(base, ...) \ \ inline decltype(struct_pack::detail::derived_decl_impl()) \ - struct_pack_derived_decl(base*); + struct_pack_derived_decl(const base*); #define STRUCT_PACK_DERIVED_IMPL(base, ...) \ STRUCT_PACK_EXPAND_EACH(, GET_STRUCT_PACK_ID_IMPL_FOR_LOOP, base, \ diff --git a/src/struct_pack/tests/test_derived.cpp b/src/struct_pack/tests/test_derived.cpp index 742044313..c0a434dc0 100644 --- a/src/struct_pack/tests/test_derived.cpp +++ b/src/struct_pack/tests/test_derived.cpp @@ -167,4 +167,55 @@ TEST_CASE("test unique_ptr with virtual base") { auto res2 = struct_pack::deserialize>(buffer2); CHECK(res2); CHECK(res2.value()->get_name() == std::make_unique()->get_name()); -} \ No newline at end of file +} + +namespace derived_class_contain_another_derived_class { + +struct base { + virtual uint32_t get_struct_pack_id() const = 0; + virtual std::string get_name() const = 0; + static std::unique_ptr deserialize(std::string& serialized); + virtual ~base(){}; +}; + +struct derived1 : public base { + int b; + virtual uint32_t get_struct_pack_id() const override; + std::string get_name() const override { return "derived1"; } +}; +STRUCT_PACK_REFL(derived1, b); + +struct derived2 : public base { + std::string c; + std::unique_ptr child; + virtual uint32_t get_struct_pack_id() const override; + std::string get_name() const override { return "derived2"; } +}; + +STRUCT_PACK_REFL(derived2, c, child); + +STRUCT_PACK_DERIVED_IMPL(base, derived1, derived2); + +std::unique_ptr base::deserialize(std::string& serialized) { + return struct_pack::deserialize_derived_class( + serialized) + .value(); +} + +} // namespace derived_class_contain_another_derived_class + +TEST_CASE("test derived class contain by other derived class") { + using namespace derived_class_contain_another_derived_class; + { + auto serialized = struct_pack::serialize(derived1{}); + auto x = base::deserialize(serialized); + REQUIRE(x); + CHECK(x->get_name() == "derived1"); + } + { + auto serialized = struct_pack::serialize(derived2{}); + auto x = base::deserialize(serialized); + REQUIRE(x); + CHECK(x->get_name() == "derived2"); + } +}