Skip to content

Commit

Permalink
[struct_pack] fixed serialize std::unique_ptr<T> with T is derived cl…
Browse files Browse the repository at this point in the history
…ass. (#634)
  • Loading branch information
poor-circle authored Mar 18, 2024
1 parent ba4685d commit 6f59fa2
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 4 deletions.
3 changes: 3 additions & 0 deletions include/ylt/struct_pack/derived_helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,9 @@ struct deserialize_one_derived_class_helper {
}
};

template <typename T>
void struct_pack_derived_decl(const T *) = delete;

template <typename Base>
using derived_class_set_t = decltype(struct_pack_derived_decl((Base *)nullptr));

Expand Down
5 changes: 2 additions & 3 deletions include/ylt/struct_pack/derived_marco.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 { \
Expand All @@ -26,7 +25,7 @@
#define STRUCT_PACK_DERIVED_DECL(base, ...) \
\
inline decltype(struct_pack::detail::derived_decl_impl<base, __VA_ARGS__>()) \
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, \
Expand Down
53 changes: 52 additions & 1 deletion src/struct_pack/tests/test_derived.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,55 @@ TEST_CASE("test unique_ptr<Base> with virtual base") {
auto res2 = struct_pack::deserialize<std::unique_ptr<base>>(buffer2);
CHECK(res2);
CHECK(res2.value()->get_name() == std::make_unique<derived4>()->get_name());
}
}

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<base> 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<derived1> 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> base::deserialize(std::string& serialized) {
return struct_pack::deserialize_derived_class<base, derived1, derived2>(
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<std::string>(derived1{});
auto x = base::deserialize(serialized);
REQUIRE(x);
CHECK(x->get_name() == "derived1");
}
{
auto serialized = struct_pack::serialize<std::string>(derived2{});
auto x = base::deserialize(serialized);
REQUIRE(x);
CHECK(x->get_name() == "derived2");
}
}

0 comments on commit 6f59fa2

Please sign in to comment.