diff --git a/include/msgpack/adaptor/detail/cpp11_define.hpp b/include/msgpack/adaptor/detail/cpp11_define.hpp index 115018fd..1287c1b3 100644 --- a/include/msgpack/adaptor/detail/cpp11_define.hpp +++ b/include/msgpack/adaptor/detail/cpp11_define.hpp @@ -43,6 +43,19 @@ msgpack::type::make_define(__VA_ARGS__).msgpack_object(o, z); \ } +#define MSGPACK_BASE(base) \ + static_cast( \ + const_cast< \ + std::add_lvalue_reference< \ + std::remove_const< \ + std::remove_pointer< \ + decltype(this) \ + >::type \ + >::type \ + >::type \ + >(*this) \ + ) + // MSGPACK_ADD_ENUM must be used in the global namespace. #define MSGPACK_ADD_ENUM(enum_name) \ namespace msgpack { \ diff --git a/test/msgpack_cpp11.cpp b/test/msgpack_cpp11.cpp index 6dd187cb..9548b2b8 100644 --- a/test/msgpack_cpp11.cpp +++ b/test/msgpack_cpp11.cpp @@ -185,4 +185,80 @@ TEST(MSGPACK_USER_DEFINED, simple_buffer_enum_class_member) EXPECT_EQ(val1.t3, val2.t3); } +struct top { + int t; + MSGPACK_DEFINE(t); +}; + +struct mid1 : top { + int m1; + MSGPACK_DEFINE(MSGPACK_BASE(top), m1); +}; + +struct mid2 : top { + int m2; + MSGPACK_DEFINE(m2, MSGPACK_BASE(top)); +}; + +struct bottom : mid1, mid2 { + int b; + MSGPACK_DEFINE(MSGPACK_BASE(mid1), MSGPACK_BASE(mid2), b); +}; + +TEST(MSGPACK_INHERIT, simple_buffer_non_virtual) +{ + bottom b; + b.b = 1; + b.m1 = 2; + b.m2 = 3; + b.mid1::t = 4; + b.mid2::t = 5; + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, b); + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size()); + bottom br = ret.get().as(); + EXPECT_EQ(b.b, br.b); + EXPECT_EQ(b.m1, br.m1); + EXPECT_EQ(b.m2, br.m2); + EXPECT_EQ(b.mid1::t, br.mid1::t); + EXPECT_EQ(b.mid2::t, br.mid2::t); +} + +struct v_top { + int t; + MSGPACK_DEFINE(t); +}; + +struct v_mid1 : virtual v_top { + int m1; + MSGPACK_DEFINE(m1); +}; + +struct v_mid2 : virtual v_top { + int m2; + MSGPACK_DEFINE(m2); +}; + +struct v_bottom : v_mid1, v_mid2 { + int b; + MSGPACK_DEFINE(MSGPACK_BASE(v_mid1), MSGPACK_BASE(v_mid2), MSGPACK_BASE(v_top), b); +}; + +TEST(MSGPACK_INHERIT, simple_buffer_virtual) +{ + v_bottom b; + b.b = 1; + b.m1 = 2; + b.m2 = 3; + b.t = 4; + msgpack::sbuffer sbuf; + msgpack::pack(sbuf, b); + msgpack::unpacked ret = msgpack::unpack(sbuf.data(), sbuf.size()); + v_bottom br = ret.get().as(); + EXPECT_EQ(b.b, br.b); + EXPECT_EQ(b.m1, br.m1); + EXPECT_EQ(b.m2, br.m2); + EXPECT_EQ(b.t, br.t); +} + #endif // !defined(MSGPACK_USE_CPP03) diff --git a/test/object_with_zone.cpp b/test/object_with_zone.cpp index c203ee46..a2d7c1e3 100644 --- a/test/object_with_zone.cpp +++ b/test/object_with_zone.cpp @@ -786,4 +786,81 @@ TEST(object_with_zone, tuple_empty) EXPECT_EQ(obj.as(), v); } -#endif +// User defined inheriting classes +struct top { + int t; + MSGPACK_DEFINE(t); +}; + +struct mid1 : top { + int m1; + MSGPACK_DEFINE(MSGPACK_BASE(top), m1); +}; + +struct mid2 : top { + int m2; + MSGPACK_DEFINE(m2, MSGPACK_BASE(top)); +}; + +struct bottom : mid1, mid2 { + int b; + MSGPACK_DEFINE(MSGPACK_BASE(mid1), MSGPACK_BASE(mid2), b); +}; + +TEST(object_with_zone, user_defined_non_virtual) +{ + bottom b; + b.b = 1; + b.m1 = 2; + b.m2 = 3; + b.mid1::t = 4; + b.mid2::t = 5; + + msgpack::zone z; + msgpack::object obj(b, z); + bottom br = obj.as(); + EXPECT_EQ(b.b, br.b); + EXPECT_EQ(b.m1, br.m1); + EXPECT_EQ(b.m2, br.m2); + EXPECT_EQ(b.mid1::t, br.mid1::t); + EXPECT_EQ(b.mid2::t, br.mid2::t); +} + +struct v_top { + int t; + MSGPACK_DEFINE(t); +}; + +struct v_mid1 : virtual v_top { + int m1; + MSGPACK_DEFINE(m1); +}; + +struct v_mid2 : virtual v_top { + int m2; + MSGPACK_DEFINE(m2); +}; + +struct v_bottom : v_mid1, v_mid2 { + int b; + MSGPACK_DEFINE(MSGPACK_BASE(v_mid1), MSGPACK_BASE(v_mid2), MSGPACK_BASE(v_top), b); +}; + +TEST(object_with_zone, user_defined_virtual) +{ + v_bottom b; + b.b = 1; + b.m1 = 2; + b.m2 = 3; + b.t = 4; + + msgpack::zone z; + msgpack::object obj(b, z); + v_bottom br = obj.as(); + EXPECT_EQ(b.b, br.b); + EXPECT_EQ(b.m1, br.m1); + EXPECT_EQ(b.m2, br.m2); + EXPECT_EQ(b.t, br.t); +} + +#endif // !defined(MSGPACK_USE_CPP03)