diff --git a/include/ylt/struct_pack.hpp b/include/ylt/struct_pack.hpp index 75584e42a..6746f3a4e 100644 --- a/include/ylt/struct_pack.hpp +++ b/include/ylt/struct_pack.hpp @@ -20,6 +20,7 @@ #include #include +#include "struct_pack/derived_marco.hpp" #include "struct_pack/struct_pack_impl.hpp" #if __has_include() && __cplusplus > 202002L @@ -91,7 +92,12 @@ STRUCT_PACK_INLINE constexpr std::uint32_t get_type_code() { static_assert(sizeof...(Args) > 0); std::uint32_t ret = 0; if constexpr (sizeof...(Args) == 1) { - ret = detail::get_types_code(); + if constexpr (std::is_abstract_v) { + struct_pack::detail::unreachable(); + } + else { + ret = detail::get_types_code(); + } } else { ret = detail::get_types_code...>>(); @@ -527,8 +533,8 @@ template >::value, "the First type should be the base class of all derived class "); - constexpr auto has_hash_collision = - struct_pack::detail::MD5_set::has_hash_collision; + constexpr auto has_hash_collision = struct_pack::detail::MD5_set< + std::tuple>::has_hash_collision; if constexpr (has_hash_collision != 0) { static_assert(!sizeof(std::tuple_element_t>), diff --git a/include/ylt/struct_pack/derived_helper.hpp b/include/ylt/struct_pack/derived_helper.hpp new file mode 100644 index 000000000..dd2990f32 --- /dev/null +++ b/include/ylt/struct_pack/derived_helper.hpp @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2023, Alibaba Group Holding Limited; + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once +#include +#include +#include +#include + +#include "error_code.hpp" +#include "marco.h" +#include "size_info.hpp" +#include "util.h" +namespace struct_pack { + +template +STRUCT_PACK_INLINE constexpr std::uint32_t get_type_code(); +namespace detail { +struct MD5_pair { + uint32_t md5; + uint32_t index; + constexpr friend bool operator<(const MD5_pair &l, const MD5_pair &r) { + return l.md5 < r.md5; + } + constexpr friend bool operator>(const MD5_pair &l, const MD5_pair &r) { + return l.md5 > r.md5; + } + constexpr friend bool operator==(const MD5_pair &l, const MD5_pair &r) { + return l.md5 == r.md5; + } +}; + +template +constexpr uint32_t get_types_code(); + +template +struct MD5_set { + static constexpr int size = std::tuple_size_v; + static_assert(size <= 256); + + private: + template + static constexpr std::array calculate_md5( + std::index_sequence) { + std::array md5{}; + ((md5[Index] = + MD5_pair{ + get_types_code>(), + Index}), + ...); + compile_time_sort(md5); + return md5; + } + static constexpr std::size_t has_hash_collision_impl() { + for (std::size_t i = 1; i < size; ++i) { + if (value[i - 1] == value[i]) { + return value[i].index; + } + } + return 0; + } + + public: + static constexpr std::array value = + calculate_md5(std::make_index_sequence()); + static constexpr std::size_t has_hash_collision = has_hash_collision_impl(); +}; + +template +struct public_base_class_checker { + static_assert(std::tuple_size_v <= 256); + + private: + template + static constexpr bool calculate_md5(std::index_sequence) { + return (std::is_base_of_v> && + ...); + } + + public: + static constexpr bool value = public_base_class_checker::calculate_md5( + std::make_index_sequence>()); +}; + +template +struct deserialize_derived_class_helper { + template + static STRUCT_PACK_INLINE constexpr struct_pack::errc run( + std::unique_ptr &base, unpack &unpacker) { + if constexpr (index >= std::tuple_size_v) { + unreachable(); + return struct_pack::errc{}; + } + else { + using derived_class = std::tuple_element_t; + base = std::make_unique(); + return unpacker.deserialize(*(derived_class *)base.get()); + } + } +}; + +template +constexpr size_info inline calculate_one_size(const T &item); + +template +struct calculate_one_size_derived_class_helper { + template + static STRUCT_PACK_INLINE constexpr size_info run(BaseClass *base) { + if constexpr (index >= std::tuple_size_v) { + unreachable(); + } + else { + using derived_class = std::tuple_element_t; +#ifdef STRUCT_PACK_RTTI_ENABLED + assert(dynamic_cast(base)); +#endif + return calculate_one_size(*(derived_class *)base); + } + } +}; + +template +struct serialize_one_derived_class_helper { + template + static STRUCT_PACK_INLINE constexpr void run(packer *self, BaseClass *base) { + if constexpr (index >= std::tuple_size_v) { + unreachable(); + } + else { + using derived_class = std::tuple_element_t; +#ifdef STRUCT_PACK_RTTI_ENABLED + assert(dynamic_cast(base)); +#endif + self->template serialize_one( + *(derived_class *)base); + } + } +}; + +template +struct deserialize_one_derived_class_helper { + template + static STRUCT_PACK_INLINE constexpr struct_pack::errc run(unpacker *self, + Pointer &base) { + if constexpr (index >= std::tuple_size_v) { + unreachable(); + } + else { + using derived_class = std::tuple_element_t; + base = std::make_unique(); + return self->template deserialize_one( + *(derived_class *)base.get()); + } + } +}; + +template +struct deserialize_one_compatible_in_derived_class_helper { + template + static STRUCT_PACK_INLINE constexpr struct_pack::errc run(unpacker *self, + Pointer &base) { + if constexpr (index >= std::tuple_size_v) { + unreachable(); + } + else { + using derived_class = std::tuple_element_t; +#ifdef STRUCT_PACK_RTTI_ENABLED + assert(dynamic_cast(base.get())); +#endif + return self->template deserialize_one( + *(derived_class *)base.get()); + } + } +}; + +template +using derived_class_set_t = decltype(struct_pack_derived_decl((Base *)nullptr)); + +template +constexpr std::size_t search_type_by_md5(uint32_t id, bool &ok) { + constexpr auto &MD5s = MD5_set>::value; + auto result = std::lower_bound(MD5s.begin(), MD5s.end(), MD5_pair{id, 0}); + ok = (result != MD5s.end() && result->md5 == id); + return result->index; +} + +template +std::uint32_t get_struct_pack_id_impl() { + if constexpr (std::is_abstract_v) { + struct_pack::detail::unreachable(); + } + else { + return struct_pack::get_type_code(); + } +} + +template +constexpr auto derived_decl_impl() { + if constexpr (std::is_abstract_v) { + return struct_pack::detail::declval>(); + } + else { + return struct_pack::detail::declval>(); + } +} +} // namespace detail +} // namespace struct_pack \ No newline at end of file diff --git a/include/ylt/struct_pack/derived_marco.hpp b/include/ylt/struct_pack/derived_marco.hpp new file mode 100644 index 000000000..28951a286 --- /dev/null +++ b/include/ylt/struct_pack/derived_marco.hpp @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2023, Alibaba Group Holding Limited; + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "foreach_macro.h" + +#pragma once +#define GET_STRUCT_PACK_ID_IMPL(type) \ + inline uint32_t type::get_struct_pack_id() const { \ + return struct_pack::detail::get_struct_pack_id_impl(); \ + } + +#define GET_STRUCT_PACK_ID_IMPL_FOR_LOOP(idx, type) \ + inline uint32_t type::get_struct_pack_id() const { \ + return struct_pack::detail::get_struct_pack_id_impl(); \ + } + +#define STRUCT_PACK_DERIVED_IMPL(base, ...) \ + \ + inline decltype(struct_pack::detail::derived_decl_impl()) \ + struct_pack_derived_decl(base*); + +#define STRUCT_PACK_DERIVED_DECL(base, ...) \ + STRUCT_PACK_EXPAND_EACH(, GET_STRUCT_PACK_ID_IMPL_FOR_LOOP, base, \ + __VA_ARGS__) \ + STRUCT_PACK_DERIVED_IMPL(base, __VA_ARGS__)\ diff --git a/include/ylt/struct_pack/foreach_macro.h b/include/ylt/struct_pack/foreach_macro.h new file mode 100644 index 000000000..764bf51f6 --- /dev/null +++ b/include/ylt/struct_pack/foreach_macro.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2023, Alibaba Group Holding Limited; + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once +// clang-format off +#define STRUCT_PACK_ARG_COUNT(...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_INTERNAL_ARG_COUNT(0, ##__VA_ARGS__,\ + 64, 63, 62, 61, 60, \ + 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ + 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ + 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ + 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) + +#define STRUCT_PACK_INTERNAL_ARG_COUNT(\ + _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, \ + _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \ + _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \ + _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \ + _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \ + _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \ + _60, _61, _62, _63, _64, N, ...) N + +#define STRUCT_PACK_CONCAT_(l, r) l ## r +#define STRUCT_PACK_CONCAT(l, r) STRUCT_PACK_CONCAT_(l, r) + +#define STRUCT_PACK_MARCO_EXPAND(...) __VA_ARGS__ + +#define STRUCT_PACK_DOARG0(s,f,o) +#define STRUCT_PACK_DOARG1(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG0(s,f,__VA_ARGS__)) s f(0,t) +#define STRUCT_PACK_DOARG2(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG1(s,f,__VA_ARGS__)) s f(1,t) +#define STRUCT_PACK_DOARG3(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG2(s,f,__VA_ARGS__)) s f(2,t) +#define STRUCT_PACK_DOARG4(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG3(s,f,__VA_ARGS__)) s f(3,t) +#define STRUCT_PACK_DOARG5(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG4(s,f,__VA_ARGS__)) s f(4,t) +#define STRUCT_PACK_DOARG6(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG5(s,f,__VA_ARGS__)) s f(5,t) +#define STRUCT_PACK_DOARG7(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG6(s,f,__VA_ARGS__)) s f(6,t) +#define STRUCT_PACK_DOARG8(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG7(s,f,__VA_ARGS__)) s f(7,t) +#define STRUCT_PACK_DOARG9(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG8(s,f,__VA_ARGS__)) s f(8,t) +#define STRUCT_PACK_DOARG10(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG9(s,f,__VA_ARGS__)) s f(9,t) +#define STRUCT_PACK_DOARG11(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG10(s,f,__VA_ARGS__)) s f(10,t) +#define STRUCT_PACK_DOARG12(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG11(s,f,__VA_ARGS__)) s f(11,t) +#define STRUCT_PACK_DOARG13(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG12(s,f,__VA_ARGS__)) s f(12,t) +#define STRUCT_PACK_DOARG14(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG13(s,f,__VA_ARGS__)) s f(13,t) +#define STRUCT_PACK_DOARG15(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG14(s,f,__VA_ARGS__)) s f(14,t) +#define STRUCT_PACK_DOARG16(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG15(s,f,__VA_ARGS__)) s f(15,t) +#define STRUCT_PACK_DOARG17(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG16(s,f,__VA_ARGS__)) s f(16,t) +#define STRUCT_PACK_DOARG18(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG17(s,f,__VA_ARGS__)) s f(17,t) +#define STRUCT_PACK_DOARG19(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG18(s,f,__VA_ARGS__)) s f(18,t) +#define STRUCT_PACK_DOARG20(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG19(s,f,__VA_ARGS__)) s f(19,t) +#define STRUCT_PACK_DOARG21(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG20(s,f,__VA_ARGS__)) s f(20,t) +#define STRUCT_PACK_DOARG22(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG21(s,f,__VA_ARGS__)) s f(21,t) +#define STRUCT_PACK_DOARG23(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG22(s,f,__VA_ARGS__)) s f(22,t) +#define STRUCT_PACK_DOARG24(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG23(s,f,__VA_ARGS__)) s f(23,t) +#define STRUCT_PACK_DOARG25(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG24(s,f,__VA_ARGS__)) s f(24,t) +#define STRUCT_PACK_DOARG26(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG25(s,f,__VA_ARGS__)) s f(25,t) +#define STRUCT_PACK_DOARG27(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG26(s,f,__VA_ARGS__)) s f(26,t) +#define STRUCT_PACK_DOARG28(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG27(s,f,__VA_ARGS__)) s f(27,t) +#define STRUCT_PACK_DOARG29(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG28(s,f,__VA_ARGS__)) s f(28,t) +#define STRUCT_PACK_DOARG30(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG29(s,f,__VA_ARGS__)) s f(29,t) +#define STRUCT_PACK_DOARG31(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG30(s,f,__VA_ARGS__)) s f(30,t) +#define STRUCT_PACK_DOARG32(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG31(s,f,__VA_ARGS__)) s f(31,t) +#define STRUCT_PACK_DOARG33(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG32(s,f,__VA_ARGS__)) s f(32,t) +#define STRUCT_PACK_DOARG34(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG33(s,f,__VA_ARGS__)) s f(33,t) +#define STRUCT_PACK_DOARG35(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG34(s,f,__VA_ARGS__)) s f(34,t) +#define STRUCT_PACK_DOARG36(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG35(s,f,__VA_ARGS__)) s f(35,t) +#define STRUCT_PACK_DOARG37(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG36(s,f,__VA_ARGS__)) s f(36,t) +#define STRUCT_PACK_DOARG38(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG37(s,f,__VA_ARGS__)) s f(37,t) +#define STRUCT_PACK_DOARG39(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG38(s,f,__VA_ARGS__)) s f(38,t) +#define STRUCT_PACK_DOARG40(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG39(s,f,__VA_ARGS__)) s f(39,t) +#define STRUCT_PACK_DOARG41(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG40(s,f,__VA_ARGS__)) s f(40,t) +#define STRUCT_PACK_DOARG42(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG41(s,f,__VA_ARGS__)) s f(41,t) +#define STRUCT_PACK_DOARG43(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG42(s,f,__VA_ARGS__)) s f(42,t) +#define STRUCT_PACK_DOARG44(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG43(s,f,__VA_ARGS__)) s f(43,t) +#define STRUCT_PACK_DOARG45(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG44(s,f,__VA_ARGS__)) s f(44,t) +#define STRUCT_PACK_DOARG46(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG45(s,f,__VA_ARGS__)) s f(45,t) +#define STRUCT_PACK_DOARG47(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG46(s,f,__VA_ARGS__)) s f(46,t) +#define STRUCT_PACK_DOARG48(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG47(s,f,__VA_ARGS__)) s f(47,t) +#define STRUCT_PACK_DOARG49(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG48(s,f,__VA_ARGS__)) s f(48,t) +#define STRUCT_PACK_DOARG50(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG49(s,f,__VA_ARGS__)) s f(49,t) +#define STRUCT_PACK_DOARG51(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG50(s,f,__VA_ARGS__)) s f(50,t) +#define STRUCT_PACK_DOARG52(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG51(s,f,__VA_ARGS__)) s f(51,t) +#define STRUCT_PACK_DOARG53(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG52(s,f,__VA_ARGS__)) s f(52,t) +#define STRUCT_PACK_DOARG54(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG53(s,f,__VA_ARGS__)) s f(53,t) +#define STRUCT_PACK_DOARG55(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG54(s,f,__VA_ARGS__)) s f(54,t) +#define STRUCT_PACK_DOARG56(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG55(s,f,__VA_ARGS__)) s f(55,t) +#define STRUCT_PACK_DOARG57(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG56(s,f,__VA_ARGS__)) s f(56,t) +#define STRUCT_PACK_DOARG58(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG57(s,f,__VA_ARGS__)) s f(57,t) +#define STRUCT_PACK_DOARG59(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG58(s,f,__VA_ARGS__)) s f(58,t) +#define STRUCT_PACK_DOARG60(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG59(s,f,__VA_ARGS__)) s f(59,t) +#define STRUCT_PACK_DOARG61(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG60(s,f,__VA_ARGS__)) s f(60,t) +#define STRUCT_PACK_DOARG62(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG61(s,f,__VA_ARGS__)) s f(61,t) +#define STRUCT_PACK_DOARG63(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG62(s,f,__VA_ARGS__)) s f(62,t) +#define STRUCT_PACK_DOARG64(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG63(s,f,__VA_ARGS__)) s f(63,t) + +#define STRUCT_PACK_MAKE_ARGS0(Type) +#define STRUCT_PACK_MAKE_ARGS1(Type) Type +#define STRUCT_PACK_MAKE_ARGS2(Type) STRUCT_PACK_MAKE_ARGS1(Type), Type +#define STRUCT_PACK_MAKE_ARGS3(Type) STRUCT_PACK_MAKE_ARGS2(Type), Type +#define STRUCT_PACK_MAKE_ARGS4(Type) STRUCT_PACK_MAKE_ARGS3(Type), Type +#define STRUCT_PACK_MAKE_ARGS5(Type) STRUCT_PACK_MAKE_ARGS4(Type), Type +#define STRUCT_PACK_MAKE_ARGS6(Type) STRUCT_PACK_MAKE_ARGS5(Type), Type +#define STRUCT_PACK_MAKE_ARGS7(Type) STRUCT_PACK_MAKE_ARGS6(Type), Type +#define STRUCT_PACK_MAKE_ARGS8(Type) STRUCT_PACK_MAKE_ARGS7(Type), Type +#define STRUCT_PACK_MAKE_ARGS9(Type) STRUCT_PACK_MAKE_ARGS8(Type), Type +#define STRUCT_PACK_MAKE_ARGS10(Type) STRUCT_PACK_MAKE_ARGS9(Type), Type +#define STRUCT_PACK_MAKE_ARGS11(Type) STRUCT_PACK_MAKE_ARGS10(Type), Type +#define STRUCT_PACK_MAKE_ARGS12(Type) STRUCT_PACK_MAKE_ARGS11(Type), Type +#define STRUCT_PACK_MAKE_ARGS13(Type) STRUCT_PACK_MAKE_ARGS12(Type), Type +#define STRUCT_PACK_MAKE_ARGS14(Type) STRUCT_PACK_MAKE_ARGS13(Type), Type +#define STRUCT_PACK_MAKE_ARGS15(Type) STRUCT_PACK_MAKE_ARGS14(Type), Type +#define STRUCT_PACK_MAKE_ARGS16(Type) STRUCT_PACK_MAKE_ARGS15(Type), Type +#define STRUCT_PACK_MAKE_ARGS17(Type) STRUCT_PACK_MAKE_ARGS16(Type), Type +#define STRUCT_PACK_MAKE_ARGS18(Type) STRUCT_PACK_MAKE_ARGS17(Type), Type +#define STRUCT_PACK_MAKE_ARGS19(Type) STRUCT_PACK_MAKE_ARGS18(Type), Type +#define STRUCT_PACK_MAKE_ARGS20(Type) STRUCT_PACK_MAKE_ARGS19(Type), Type +#define STRUCT_PACK_MAKE_ARGS21(Type) STRUCT_PACK_MAKE_ARGS20(Type), Type +#define STRUCT_PACK_MAKE_ARGS22(Type) STRUCT_PACK_MAKE_ARGS21(Type), Type +#define STRUCT_PACK_MAKE_ARGS23(Type) STRUCT_PACK_MAKE_ARGS22(Type), Type +#define STRUCT_PACK_MAKE_ARGS24(Type) STRUCT_PACK_MAKE_ARGS23(Type), Type +#define STRUCT_PACK_MAKE_ARGS25(Type) STRUCT_PACK_MAKE_ARGS24(Type), Type +#define STRUCT_PACK_MAKE_ARGS26(Type) STRUCT_PACK_MAKE_ARGS25(Type), Type +#define STRUCT_PACK_MAKE_ARGS27(Type) STRUCT_PACK_MAKE_ARGS26(Type), Type +#define STRUCT_PACK_MAKE_ARGS28(Type) STRUCT_PACK_MAKE_ARGS27(Type), Type +#define STRUCT_PACK_MAKE_ARGS29(Type) STRUCT_PACK_MAKE_ARGS28(Type), Type +#define STRUCT_PACK_MAKE_ARGS30(Type) STRUCT_PACK_MAKE_ARGS29(Type), Type +#define STRUCT_PACK_MAKE_ARGS31(Type) STRUCT_PACK_MAKE_ARGS30(Type), Type +#define STRUCT_PACK_MAKE_ARGS32(Type) STRUCT_PACK_MAKE_ARGS31(Type), Type +#define STRUCT_PACK_MAKE_ARGS33(Type) STRUCT_PACK_MAKE_ARGS32(Type), Type +#define STRUCT_PACK_MAKE_ARGS34(Type) STRUCT_PACK_MAKE_ARGS33(Type), Type +#define STRUCT_PACK_MAKE_ARGS35(Type) STRUCT_PACK_MAKE_ARGS34(Type), Type +#define STRUCT_PACK_MAKE_ARGS36(Type) STRUCT_PACK_MAKE_ARGS35(Type), Type +#define STRUCT_PACK_MAKE_ARGS37(Type) STRUCT_PACK_MAKE_ARGS36(Type), Type +#define STRUCT_PACK_MAKE_ARGS38(Type) STRUCT_PACK_MAKE_ARGS37(Type), Type +#define STRUCT_PACK_MAKE_ARGS39(Type) STRUCT_PACK_MAKE_ARGS38(Type), Type +#define STRUCT_PACK_MAKE_ARGS40(Type) STRUCT_PACK_MAKE_ARGS39(Type), Type +#define STRUCT_PACK_MAKE_ARGS41(Type) STRUCT_PACK_MAKE_ARGS40(Type), Type +#define STRUCT_PACK_MAKE_ARGS42(Type) STRUCT_PACK_MAKE_ARGS41(Type), Type +#define STRUCT_PACK_MAKE_ARGS43(Type) STRUCT_PACK_MAKE_ARGS42(Type), Type +#define STRUCT_PACK_MAKE_ARGS44(Type) STRUCT_PACK_MAKE_ARGS43(Type), Type +#define STRUCT_PACK_MAKE_ARGS45(Type) STRUCT_PACK_MAKE_ARGS44(Type), Type +#define STRUCT_PACK_MAKE_ARGS46(Type) STRUCT_PACK_MAKE_ARGS45(Type), Type +#define STRUCT_PACK_MAKE_ARGS47(Type) STRUCT_PACK_MAKE_ARGS46(Type), Type +#define STRUCT_PACK_MAKE_ARGS48(Type) STRUCT_PACK_MAKE_ARGS47(Type), Type +#define STRUCT_PACK_MAKE_ARGS49(Type) STRUCT_PACK_MAKE_ARGS48(Type), Type +#define STRUCT_PACK_MAKE_ARGS50(Type) STRUCT_PACK_MAKE_ARGS49(Type), Type +#define STRUCT_PACK_MAKE_ARGS51(Type) STRUCT_PACK_MAKE_ARGS50(Type), Type +#define STRUCT_PACK_MAKE_ARGS52(Type) STRUCT_PACK_MAKE_ARGS51(Type), Type +#define STRUCT_PACK_MAKE_ARGS53(Type) STRUCT_PACK_MAKE_ARGS52(Type), Type +#define STRUCT_PACK_MAKE_ARGS54(Type) STRUCT_PACK_MAKE_ARGS53(Type), Type +#define STRUCT_PACK_MAKE_ARGS55(Type) STRUCT_PACK_MAKE_ARGS54(Type), Type +#define STRUCT_PACK_MAKE_ARGS56(Type) STRUCT_PACK_MAKE_ARGS55(Type), Type +#define STRUCT_PACK_MAKE_ARGS57(Type) STRUCT_PACK_MAKE_ARGS56(Type), Type +#define STRUCT_PACK_MAKE_ARGS58(Type) STRUCT_PACK_MAKE_ARGS57(Type), Type +#define STRUCT_PACK_MAKE_ARGS59(Type) STRUCT_PACK_MAKE_ARGS58(Type), Type +#define STRUCT_PACK_MAKE_ARGS60(Type) STRUCT_PACK_MAKE_ARGS59(Type), Type +#define STRUCT_PACK_MAKE_ARGS61(Type) STRUCT_PACK_MAKE_ARGS60(Type), Type +#define STRUCT_PACK_MAKE_ARGS62(Type) STRUCT_PACK_MAKE_ARGS61(Type), Type +#define STRUCT_PACK_MAKE_ARGS63(Type) STRUCT_PACK_MAKE_ARGS62(Type), Type +#define STRUCT_PACK_MAKE_ARGS64(Type) STRUCT_PACK_MAKE_ARGS63(Type), Type + + +#define STRUCT_PACK_MAKE_ARGS(Type,Count) \ + STRUCT_PACK_CONCAT(STRUCT_PACK_MAKE_ARGS,Count)(Type) + +#define STRUCT_PACK_EXPAND_EACH_(sepatator,fun,...) \ + STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_CONCAT(STRUCT_PACK_DOARG,STRUCT_PACK_ARG_COUNT(__VA_ARGS__))(sepatator,fun,__VA_ARGS__)) +#define STRUCT_PACK_EXPAND_EACH(sepatator,fun,...) \ + STRUCT_PACK_EXPAND_EACH_(sepatator,fun,__VA_ARGS__) \ No newline at end of file diff --git a/include/ylt/struct_pack/marco.h b/include/ylt/struct_pack/marco.h index 435485f48..5ea4bcd31 100644 --- a/include/ylt/struct_pack/marco.h +++ b/include/ylt/struct_pack/marco.h @@ -46,3 +46,17 @@ #else #define SP_UNLIKELY(expr) (expr) #endif + +#if defined(__clang__) +#if __has_feature(cxx_rtti) +#define STRUCT_PACK_RTTI_ENABLED +#endif +#elif defined(__GNUC__) +#if defined(__GXX_RTTI) +#define STRUCT_PACK_RTTI_ENABLED +#endif +#elif defined(_MSC_VER) +#if defined(_CPPRTTI) +#define STRUCT_PACK_RTTI_ENABLED +#endif +#endif diff --git a/include/ylt/struct_pack/reflection.hpp b/include/ylt/struct_pack/reflection.hpp index 7b888555a..1d41725d7 100644 --- a/include/ylt/struct_pack/reflection.hpp +++ b/include/ylt/struct_pack/reflection.hpp @@ -30,7 +30,10 @@ #include #endif +#include "derived_helper.hpp" +#include "foreach_macro.h" #include "marco.h" +#include "util.h" namespace struct_pack { namespace detail { @@ -38,22 +41,6 @@ namespace detail { template using remove_cvref_t = std::remove_cv_t>; -[[noreturn]] inline void unreachable() { - // Uses compiler specific extensions if possible. - // Even if no extension is used, undefined behavior is still raised by - // an empty function body and the noreturn attribute. -#ifdef __GNUC__ // GCC, Clang, ICC - __builtin_unreachable(); -#elif defined(_MSC_VER) // msvc - __assume(false); -#endif -} - -template -[[noreturn]] constexpr T declval() { - unreachable(); -} - template constexpr auto get_types(); @@ -180,6 +167,13 @@ concept has_user_defined_id_ADL = requires { struct_pack_id((T*)nullptr)>; }; + +template +concept is_base_class = requires (T* t){ + std::is_same_vget_struct_pack_id())>; + typename struct_pack::detail::derived_class_set_t; +}; + #else template @@ -1572,520 +1566,520 @@ namespace detail { // clang-format off template constexpr decltype(auto) STRUCT_PACK_INLINE template_switch(std::size_t index, - Args &...args) { + Args &&...args) { switch (index) { case 0: - return Func::template run<0>(args...); + return Func::template run<0>(std::forward(args)...); case 1: - return Func::template run<1>(args...); + return Func::template run<1>(std::forward(args)...); case 2: - return Func::template run<2>(args...); + return Func::template run<2>(std::forward(args)...); case 3: - return Func::template run<3>(args...); + return Func::template run<3>(std::forward(args)...); case 4: - return Func::template run<4>(args...); + return Func::template run<4>(std::forward(args)...); case 5: - return Func::template run<5>(args...); + return Func::template run<5>(std::forward(args)...); case 6: - return Func::template run<6>(args...); + return Func::template run<6>(std::forward(args)...); case 7: - return Func::template run<7>(args...); + return Func::template run<7>(std::forward(args)...); case 8: - return Func::template run<8>(args...); + return Func::template run<8>(std::forward(args)...); case 9: - return Func::template run<9>(args...); + return Func::template run<9>(std::forward(args)...); case 10: - return Func::template run<10>(args...); + return Func::template run<10>(std::forward(args)...); case 11: - return Func::template run<11>(args...); + return Func::template run<11>(std::forward(args)...); case 12: - return Func::template run<12>(args...); + return Func::template run<12>(std::forward(args)...); case 13: - return Func::template run<13>(args...); + return Func::template run<13>(std::forward(args)...); case 14: - return Func::template run<14>(args...); + return Func::template run<14>(std::forward(args)...); case 15: - return Func::template run<15>(args...); + return Func::template run<15>(std::forward(args)...); case 16: - return Func::template run<16>(args...); + return Func::template run<16>(std::forward(args)...); case 17: - return Func::template run<17>(args...); + return Func::template run<17>(std::forward(args)...); case 18: - return Func::template run<18>(args...); + return Func::template run<18>(std::forward(args)...); case 19: - return Func::template run<19>(args...); + return Func::template run<19>(std::forward(args)...); case 20: - return Func::template run<20>(args...); + return Func::template run<20>(std::forward(args)...); case 21: - return Func::template run<21>(args...); + return Func::template run<21>(std::forward(args)...); case 22: - return Func::template run<22>(args...); + return Func::template run<22>(std::forward(args)...); case 23: - return Func::template run<23>(args...); + return Func::template run<23>(std::forward(args)...); case 24: - return Func::template run<24>(args...); + return Func::template run<24>(std::forward(args)...); case 25: - return Func::template run<25>(args...); + return Func::template run<25>(std::forward(args)...); case 26: - return Func::template run<26>(args...); + return Func::template run<26>(std::forward(args)...); case 27: - return Func::template run<27>(args...); + return Func::template run<27>(std::forward(args)...); case 28: - return Func::template run<28>(args...); + return Func::template run<28>(std::forward(args)...); case 29: - return Func::template run<29>(args...); + return Func::template run<29>(std::forward(args)...); case 30: - return Func::template run<30>(args...); + return Func::template run<30>(std::forward(args)...); case 31: - return Func::template run<31>(args...); + return Func::template run<31>(std::forward(args)...); case 32: - return Func::template run<32>(args...); + return Func::template run<32>(std::forward(args)...); case 33: - return Func::template run<33>(args...); + return Func::template run<33>(std::forward(args)...); case 34: - return Func::template run<34>(args...); + return Func::template run<34>(std::forward(args)...); case 35: - return Func::template run<35>(args...); + return Func::template run<35>(std::forward(args)...); case 36: - return Func::template run<36>(args...); + return Func::template run<36>(std::forward(args)...); case 37: - return Func::template run<37>(args...); + return Func::template run<37>(std::forward(args)...); case 38: - return Func::template run<38>(args...); + return Func::template run<38>(std::forward(args)...); case 39: - return Func::template run<39>(args...); + return Func::template run<39>(std::forward(args)...); case 40: - return Func::template run<40>(args...); + return Func::template run<40>(std::forward(args)...); case 41: - return Func::template run<41>(args...); + return Func::template run<41>(std::forward(args)...); case 42: - return Func::template run<42>(args...); + return Func::template run<42>(std::forward(args)...); case 43: - return Func::template run<43>(args...); + return Func::template run<43>(std::forward(args)...); case 44: - return Func::template run<44>(args...); + return Func::template run<44>(std::forward(args)...); case 45: - return Func::template run<45>(args...); + return Func::template run<45>(std::forward(args)...); case 46: - return Func::template run<46>(args...); + return Func::template run<46>(std::forward(args)...); case 47: - return Func::template run<47>(args...); + return Func::template run<47>(std::forward(args)...); case 48: - return Func::template run<48>(args...); + return Func::template run<48>(std::forward(args)...); case 49: - return Func::template run<49>(args...); + return Func::template run<49>(std::forward(args)...); case 50: - return Func::template run<50>(args...); + return Func::template run<50>(std::forward(args)...); case 51: - return Func::template run<51>(args...); + return Func::template run<51>(std::forward(args)...); case 52: - return Func::template run<52>(args...); + return Func::template run<52>(std::forward(args)...); case 53: - return Func::template run<53>(args...); + return Func::template run<53>(std::forward(args)...); case 54: - return Func::template run<54>(args...); + return Func::template run<54>(std::forward(args)...); case 55: - return Func::template run<55>(args...); + return Func::template run<55>(std::forward(args)...); case 56: - return Func::template run<56>(args...); + return Func::template run<56>(std::forward(args)...); case 57: - return Func::template run<57>(args...); + return Func::template run<57>(std::forward(args)...); case 58: - return Func::template run<58>(args...); + return Func::template run<58>(std::forward(args)...); case 59: - return Func::template run<59>(args...); + return Func::template run<59>(std::forward(args)...); case 60: - return Func::template run<60>(args...); + return Func::template run<60>(std::forward(args)...); case 61: - return Func::template run<61>(args...); + return Func::template run<61>(std::forward(args)...); case 62: - return Func::template run<62>(args...); + return Func::template run<62>(std::forward(args)...); case 63: - return Func::template run<63>(args...); + return Func::template run<63>(std::forward(args)...); case 64: - return Func::template run<64>(args...); + return Func::template run<64>(std::forward(args)...); case 65: - return Func::template run<65>(args...); + return Func::template run<65>(std::forward(args)...); case 66: - return Func::template run<66>(args...); + return Func::template run<66>(std::forward(args)...); case 67: - return Func::template run<67>(args...); + return Func::template run<67>(std::forward(args)...); case 68: - return Func::template run<68>(args...); + return Func::template run<68>(std::forward(args)...); case 69: - return Func::template run<69>(args...); + return Func::template run<69>(std::forward(args)...); case 70: - return Func::template run<70>(args...); + return Func::template run<70>(std::forward(args)...); case 71: - return Func::template run<71>(args...); + return Func::template run<71>(std::forward(args)...); case 72: - return Func::template run<72>(args...); + return Func::template run<72>(std::forward(args)...); case 73: - return Func::template run<73>(args...); + return Func::template run<73>(std::forward(args)...); case 74: - return Func::template run<74>(args...); + return Func::template run<74>(std::forward(args)...); case 75: - return Func::template run<75>(args...); + return Func::template run<75>(std::forward(args)...); case 76: - return Func::template run<76>(args...); + return Func::template run<76>(std::forward(args)...); case 77: - return Func::template run<77>(args...); + return Func::template run<77>(std::forward(args)...); case 78: - return Func::template run<78>(args...); + return Func::template run<78>(std::forward(args)...); case 79: - return Func::template run<79>(args...); + return Func::template run<79>(std::forward(args)...); case 80: - return Func::template run<80>(args...); + return Func::template run<80>(std::forward(args)...); case 81: - return Func::template run<81>(args...); + return Func::template run<81>(std::forward(args)...); case 82: - return Func::template run<82>(args...); + return Func::template run<82>(std::forward(args)...); case 83: - return Func::template run<83>(args...); + return Func::template run<83>(std::forward(args)...); case 84: - return Func::template run<84>(args...); + return Func::template run<84>(std::forward(args)...); case 85: - return Func::template run<85>(args...); + return Func::template run<85>(std::forward(args)...); case 86: - return Func::template run<86>(args...); + return Func::template run<86>(std::forward(args)...); case 87: - return Func::template run<87>(args...); + return Func::template run<87>(std::forward(args)...); case 88: - return Func::template run<88>(args...); + return Func::template run<88>(std::forward(args)...); case 89: - return Func::template run<89>(args...); + return Func::template run<89>(std::forward(args)...); case 90: - return Func::template run<90>(args...); + return Func::template run<90>(std::forward(args)...); case 91: - return Func::template run<91>(args...); + return Func::template run<91>(std::forward(args)...); case 92: - return Func::template run<92>(args...); + return Func::template run<92>(std::forward(args)...); case 93: - return Func::template run<93>(args...); + return Func::template run<93>(std::forward(args)...); case 94: - return Func::template run<94>(args...); + return Func::template run<94>(std::forward(args)...); case 95: - return Func::template run<95>(args...); + return Func::template run<95>(std::forward(args)...); case 96: - return Func::template run<96>(args...); + return Func::template run<96>(std::forward(args)...); case 97: - return Func::template run<97>(args...); + return Func::template run<97>(std::forward(args)...); case 98: - return Func::template run<98>(args...); + return Func::template run<98>(std::forward(args)...); case 99: - return Func::template run<99>(args...); + return Func::template run<99>(std::forward(args)...); case 100: - return Func::template run<100>(args...); + return Func::template run<100>(std::forward(args)...); case 101: - return Func::template run<101>(args...); + return Func::template run<101>(std::forward(args)...); case 102: - return Func::template run<102>(args...); + return Func::template run<102>(std::forward(args)...); case 103: - return Func::template run<103>(args...); + return Func::template run<103>(std::forward(args)...); case 104: - return Func::template run<104>(args...); + return Func::template run<104>(std::forward(args)...); case 105: - return Func::template run<105>(args...); + return Func::template run<105>(std::forward(args)...); case 106: - return Func::template run<106>(args...); + return Func::template run<106>(std::forward(args)...); case 107: - return Func::template run<107>(args...); + return Func::template run<107>(std::forward(args)...); case 108: - return Func::template run<108>(args...); + return Func::template run<108>(std::forward(args)...); case 109: - return Func::template run<109>(args...); + return Func::template run<109>(std::forward(args)...); case 110: - return Func::template run<110>(args...); + return Func::template run<110>(std::forward(args)...); case 111: - return Func::template run<111>(args...); + return Func::template run<111>(std::forward(args)...); case 112: - return Func::template run<112>(args...); + return Func::template run<112>(std::forward(args)...); case 113: - return Func::template run<113>(args...); + return Func::template run<113>(std::forward(args)...); case 114: - return Func::template run<114>(args...); + return Func::template run<114>(std::forward(args)...); case 115: - return Func::template run<115>(args...); + return Func::template run<115>(std::forward(args)...); case 116: - return Func::template run<116>(args...); + return Func::template run<116>(std::forward(args)...); case 117: - return Func::template run<117>(args...); + return Func::template run<117>(std::forward(args)...); case 118: - return Func::template run<118>(args...); + return Func::template run<118>(std::forward(args)...); case 119: - return Func::template run<119>(args...); + return Func::template run<119>(std::forward(args)...); case 120: - return Func::template run<120>(args...); + return Func::template run<120>(std::forward(args)...); case 121: - return Func::template run<121>(args...); + return Func::template run<121>(std::forward(args)...); case 122: - return Func::template run<122>(args...); + return Func::template run<122>(std::forward(args)...); case 123: - return Func::template run<123>(args...); + return Func::template run<123>(std::forward(args)...); case 124: - return Func::template run<124>(args...); + return Func::template run<124>(std::forward(args)...); case 125: - return Func::template run<125>(args...); + return Func::template run<125>(std::forward(args)...); case 126: - return Func::template run<126>(args...); + return Func::template run<126>(std::forward(args)...); case 127: - return Func::template run<127>(args...); + return Func::template run<127>(std::forward(args)...); case 128: - return Func::template run<128>(args...); + return Func::template run<128>(std::forward(args)...); case 129: - return Func::template run<129>(args...); + return Func::template run<129>(std::forward(args)...); case 130: - return Func::template run<130>(args...); + return Func::template run<130>(std::forward(args)...); case 131: - return Func::template run<131>(args...); + return Func::template run<131>(std::forward(args)...); case 132: - return Func::template run<132>(args...); + return Func::template run<132>(std::forward(args)...); case 133: - return Func::template run<133>(args...); + return Func::template run<133>(std::forward(args)...); case 134: - return Func::template run<134>(args...); + return Func::template run<134>(std::forward(args)...); case 135: - return Func::template run<135>(args...); + return Func::template run<135>(std::forward(args)...); case 136: - return Func::template run<136>(args...); + return Func::template run<136>(std::forward(args)...); case 137: - return Func::template run<137>(args...); + return Func::template run<137>(std::forward(args)...); case 138: - return Func::template run<138>(args...); + return Func::template run<138>(std::forward(args)...); case 139: - return Func::template run<139>(args...); + return Func::template run<139>(std::forward(args)...); case 140: - return Func::template run<140>(args...); + return Func::template run<140>(std::forward(args)...); case 141: - return Func::template run<141>(args...); + return Func::template run<141>(std::forward(args)...); case 142: - return Func::template run<142>(args...); + return Func::template run<142>(std::forward(args)...); case 143: - return Func::template run<143>(args...); + return Func::template run<143>(std::forward(args)...); case 144: - return Func::template run<144>(args...); + return Func::template run<144>(std::forward(args)...); case 145: - return Func::template run<145>(args...); + return Func::template run<145>(std::forward(args)...); case 146: - return Func::template run<146>(args...); + return Func::template run<146>(std::forward(args)...); case 147: - return Func::template run<147>(args...); + return Func::template run<147>(std::forward(args)...); case 148: - return Func::template run<148>(args...); + return Func::template run<148>(std::forward(args)...); case 149: - return Func::template run<149>(args...); + return Func::template run<149>(std::forward(args)...); case 150: - return Func::template run<150>(args...); + return Func::template run<150>(std::forward(args)...); case 151: - return Func::template run<151>(args...); + return Func::template run<151>(std::forward(args)...); case 152: - return Func::template run<152>(args...); + return Func::template run<152>(std::forward(args)...); case 153: - return Func::template run<153>(args...); + return Func::template run<153>(std::forward(args)...); case 154: - return Func::template run<154>(args...); + return Func::template run<154>(std::forward(args)...); case 155: - return Func::template run<155>(args...); + return Func::template run<155>(std::forward(args)...); case 156: - return Func::template run<156>(args...); + return Func::template run<156>(std::forward(args)...); case 157: - return Func::template run<157>(args...); + return Func::template run<157>(std::forward(args)...); case 158: - return Func::template run<158>(args...); + return Func::template run<158>(std::forward(args)...); case 159: - return Func::template run<159>(args...); + return Func::template run<159>(std::forward(args)...); case 160: - return Func::template run<160>(args...); + return Func::template run<160>(std::forward(args)...); case 161: - return Func::template run<161>(args...); + return Func::template run<161>(std::forward(args)...); case 162: - return Func::template run<162>(args...); + return Func::template run<162>(std::forward(args)...); case 163: - return Func::template run<163>(args...); + return Func::template run<163>(std::forward(args)...); case 164: - return Func::template run<164>(args...); + return Func::template run<164>(std::forward(args)...); case 165: - return Func::template run<165>(args...); + return Func::template run<165>(std::forward(args)...); case 166: - return Func::template run<166>(args...); + return Func::template run<166>(std::forward(args)...); case 167: - return Func::template run<167>(args...); + return Func::template run<167>(std::forward(args)...); case 168: - return Func::template run<168>(args...); + return Func::template run<168>(std::forward(args)...); case 169: - return Func::template run<169>(args...); + return Func::template run<169>(std::forward(args)...); case 170: - return Func::template run<170>(args...); + return Func::template run<170>(std::forward(args)...); case 171: - return Func::template run<171>(args...); + return Func::template run<171>(std::forward(args)...); case 172: - return Func::template run<172>(args...); + return Func::template run<172>(std::forward(args)...); case 173: - return Func::template run<173>(args...); + return Func::template run<173>(std::forward(args)...); case 174: - return Func::template run<174>(args...); + return Func::template run<174>(std::forward(args)...); case 175: - return Func::template run<175>(args...); + return Func::template run<175>(std::forward(args)...); case 176: - return Func::template run<176>(args...); + return Func::template run<176>(std::forward(args)...); case 177: - return Func::template run<177>(args...); + return Func::template run<177>(std::forward(args)...); case 178: - return Func::template run<178>(args...); + return Func::template run<178>(std::forward(args)...); case 179: - return Func::template run<179>(args...); + return Func::template run<179>(std::forward(args)...); case 180: - return Func::template run<180>(args...); + return Func::template run<180>(std::forward(args)...); case 181: - return Func::template run<181>(args...); + return Func::template run<181>(std::forward(args)...); case 182: - return Func::template run<182>(args...); + return Func::template run<182>(std::forward(args)...); case 183: - return Func::template run<183>(args...); + return Func::template run<183>(std::forward(args)...); case 184: - return Func::template run<184>(args...); + return Func::template run<184>(std::forward(args)...); case 185: - return Func::template run<185>(args...); + return Func::template run<185>(std::forward(args)...); case 186: - return Func::template run<186>(args...); + return Func::template run<186>(std::forward(args)...); case 187: - return Func::template run<187>(args...); + return Func::template run<187>(std::forward(args)...); case 188: - return Func::template run<188>(args...); + return Func::template run<188>(std::forward(args)...); case 189: - return Func::template run<189>(args...); + return Func::template run<189>(std::forward(args)...); case 190: - return Func::template run<190>(args...); + return Func::template run<190>(std::forward(args)...); case 191: - return Func::template run<191>(args...); + return Func::template run<191>(std::forward(args)...); case 192: - return Func::template run<192>(args...); + return Func::template run<192>(std::forward(args)...); case 193: - return Func::template run<193>(args...); + return Func::template run<193>(std::forward(args)...); case 194: - return Func::template run<194>(args...); + return Func::template run<194>(std::forward(args)...); case 195: - return Func::template run<195>(args...); + return Func::template run<195>(std::forward(args)...); case 196: - return Func::template run<196>(args...); + return Func::template run<196>(std::forward(args)...); case 197: - return Func::template run<197>(args...); + return Func::template run<197>(std::forward(args)...); case 198: - return Func::template run<198>(args...); + return Func::template run<198>(std::forward(args)...); case 199: - return Func::template run<199>(args...); + return Func::template run<199>(std::forward(args)...); case 200: - return Func::template run<200>(args...); + return Func::template run<200>(std::forward(args)...); case 201: - return Func::template run<201>(args...); + return Func::template run<201>(std::forward(args)...); case 202: - return Func::template run<202>(args...); + return Func::template run<202>(std::forward(args)...); case 203: - return Func::template run<203>(args...); + return Func::template run<203>(std::forward(args)...); case 204: - return Func::template run<204>(args...); + return Func::template run<204>(std::forward(args)...); case 205: - return Func::template run<205>(args...); + return Func::template run<205>(std::forward(args)...); case 206: - return Func::template run<206>(args...); + return Func::template run<206>(std::forward(args)...); case 207: - return Func::template run<207>(args...); + return Func::template run<207>(std::forward(args)...); case 208: - return Func::template run<208>(args...); + return Func::template run<208>(std::forward(args)...); case 209: - return Func::template run<209>(args...); + return Func::template run<209>(std::forward(args)...); case 210: - return Func::template run<210>(args...); + return Func::template run<210>(std::forward(args)...); case 211: - return Func::template run<211>(args...); + return Func::template run<211>(std::forward(args)...); case 212: - return Func::template run<212>(args...); + return Func::template run<212>(std::forward(args)...); case 213: - return Func::template run<213>(args...); + return Func::template run<213>(std::forward(args)...); case 214: - return Func::template run<214>(args...); + return Func::template run<214>(std::forward(args)...); case 215: - return Func::template run<215>(args...); + return Func::template run<215>(std::forward(args)...); case 216: - return Func::template run<216>(args...); + return Func::template run<216>(std::forward(args)...); case 217: - return Func::template run<217>(args...); + return Func::template run<217>(std::forward(args)...); case 218: - return Func::template run<218>(args...); + return Func::template run<218>(std::forward(args)...); case 219: - return Func::template run<219>(args...); + return Func::template run<219>(std::forward(args)...); case 220: - return Func::template run<220>(args...); + return Func::template run<220>(std::forward(args)...); case 221: - return Func::template run<221>(args...); + return Func::template run<221>(std::forward(args)...); case 222: - return Func::template run<222>(args...); + return Func::template run<222>(std::forward(args)...); case 223: - return Func::template run<223>(args...); + return Func::template run<223>(std::forward(args)...); case 224: - return Func::template run<224>(args...); + return Func::template run<224>(std::forward(args)...); case 225: - return Func::template run<225>(args...); + return Func::template run<225>(std::forward(args)...); case 226: - return Func::template run<226>(args...); + return Func::template run<226>(std::forward(args)...); case 227: - return Func::template run<227>(args...); + return Func::template run<227>(std::forward(args)...); case 228: - return Func::template run<228>(args...); + return Func::template run<228>(std::forward(args)...); case 229: - return Func::template run<229>(args...); + return Func::template run<229>(std::forward(args)...); case 230: - return Func::template run<230>(args...); + return Func::template run<230>(std::forward(args)...); case 231: - return Func::template run<231>(args...); + return Func::template run<231>(std::forward(args)...); case 232: - return Func::template run<232>(args...); + return Func::template run<232>(std::forward(args)...); case 233: - return Func::template run<233>(args...); + return Func::template run<233>(std::forward(args)...); case 234: - return Func::template run<234>(args...); + return Func::template run<234>(std::forward(args)...); case 235: - return Func::template run<235>(args...); + return Func::template run<235>(std::forward(args)...); case 236: - return Func::template run<236>(args...); + return Func::template run<236>(std::forward(args)...); case 237: - return Func::template run<237>(args...); + return Func::template run<237>(std::forward(args)...); case 238: - return Func::template run<238>(args...); + return Func::template run<238>(std::forward(args)...); case 239: - return Func::template run<239>(args...); + return Func::template run<239>(std::forward(args)...); case 240: - return Func::template run<240>(args...); + return Func::template run<240>(std::forward(args)...); case 241: - return Func::template run<241>(args...); + return Func::template run<241>(std::forward(args)...); case 242: - return Func::template run<242>(args...); + return Func::template run<242>(std::forward(args)...); case 243: - return Func::template run<243>(args...); + return Func::template run<243>(std::forward(args)...); case 244: - return Func::template run<244>(args...); + return Func::template run<244>(std::forward(args)...); case 245: - return Func::template run<245>(args...); + return Func::template run<245>(std::forward(args)...); case 246: - return Func::template run<246>(args...); + return Func::template run<246>(std::forward(args)...); case 247: - return Func::template run<247>(args...); + return Func::template run<247>(std::forward(args)...); case 248: - return Func::template run<248>(args...); + return Func::template run<248>(std::forward(args)...); case 249: - return Func::template run<249>(args...); + return Func::template run<249>(std::forward(args)...); case 250: - return Func::template run<250>(args...); + return Func::template run<250>(std::forward(args)...); case 251: - return Func::template run<251>(args...); + return Func::template run<251>(std::forward(args)...); case 252: - return Func::template run<252>(args...); + return Func::template run<252>(std::forward(args)...); case 253: - return Func::template run<253>(args...); + return Func::template run<253>(std::forward(args)...); case 254: - return Func::template run<254>(args...); + return Func::template run<254>(std::forward(args)...); case 255: - return Func::template run<255>(args...); + return Func::template run<255>(std::forward(args)...); default: unreachable(); // index shouldn't bigger than 256 @@ -2095,169 +2089,7 @@ constexpr decltype(auto) STRUCT_PACK_INLINE template_switch(std::size_t index, } // namespace struct_pack // clang-format off -#define STRUCT_PACK_ARG_COUNT(...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_INTERNAL_ARG_COUNT(0, ##__VA_ARGS__,\ - 64, 63, 62, 61, 60, \ - 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \ - 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \ - 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \ - 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \ - 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \ - 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)) - -#define STRUCT_PACK_INTERNAL_ARG_COUNT(\ - _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, \ - _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \ - _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \ - _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \ - _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \ - _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \ - _60, _61, _62, _63, _64, N, ...) N - -#define STRUCT_PACK_CONCAT_(l, r) l ## r -#define STRUCT_PACK_CONCAT(l, r) STRUCT_PACK_CONCAT_(l, r) - -#define STRUCT_PACK_MARCO_EXPAND(...) __VA_ARGS__ - -#define STRUCT_PACK_DOARG0(s,f,o) -#define STRUCT_PACK_DOARG1(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG0(s,f,__VA_ARGS__)) s f(0,t) -#define STRUCT_PACK_DOARG2(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG1(s,f,__VA_ARGS__)) s f(1,t) -#define STRUCT_PACK_DOARG3(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG2(s,f,__VA_ARGS__)) s f(2,t) -#define STRUCT_PACK_DOARG4(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG3(s,f,__VA_ARGS__)) s f(3,t) -#define STRUCT_PACK_DOARG5(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG4(s,f,__VA_ARGS__)) s f(4,t) -#define STRUCT_PACK_DOARG6(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG5(s,f,__VA_ARGS__)) s f(5,t) -#define STRUCT_PACK_DOARG7(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG6(s,f,__VA_ARGS__)) s f(6,t) -#define STRUCT_PACK_DOARG8(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG7(s,f,__VA_ARGS__)) s f(7,t) -#define STRUCT_PACK_DOARG9(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG8(s,f,__VA_ARGS__)) s f(8,t) -#define STRUCT_PACK_DOARG10(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG9(s,f,__VA_ARGS__)) s f(9,t) -#define STRUCT_PACK_DOARG11(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG10(s,f,__VA_ARGS__)) s f(10,t) -#define STRUCT_PACK_DOARG12(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG11(s,f,__VA_ARGS__)) s f(11,t) -#define STRUCT_PACK_DOARG13(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG12(s,f,__VA_ARGS__)) s f(12,t) -#define STRUCT_PACK_DOARG14(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG13(s,f,__VA_ARGS__)) s f(13,t) -#define STRUCT_PACK_DOARG15(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG14(s,f,__VA_ARGS__)) s f(14,t) -#define STRUCT_PACK_DOARG16(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG15(s,f,__VA_ARGS__)) s f(15,t) -#define STRUCT_PACK_DOARG17(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG16(s,f,__VA_ARGS__)) s f(16,t) -#define STRUCT_PACK_DOARG18(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG17(s,f,__VA_ARGS__)) s f(17,t) -#define STRUCT_PACK_DOARG19(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG18(s,f,__VA_ARGS__)) s f(18,t) -#define STRUCT_PACK_DOARG20(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG19(s,f,__VA_ARGS__)) s f(19,t) -#define STRUCT_PACK_DOARG21(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG20(s,f,__VA_ARGS__)) s f(20,t) -#define STRUCT_PACK_DOARG22(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG21(s,f,__VA_ARGS__)) s f(21,t) -#define STRUCT_PACK_DOARG23(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG22(s,f,__VA_ARGS__)) s f(22,t) -#define STRUCT_PACK_DOARG24(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG23(s,f,__VA_ARGS__)) s f(23,t) -#define STRUCT_PACK_DOARG25(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG24(s,f,__VA_ARGS__)) s f(24,t) -#define STRUCT_PACK_DOARG26(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG25(s,f,__VA_ARGS__)) s f(25,t) -#define STRUCT_PACK_DOARG27(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG26(s,f,__VA_ARGS__)) s f(26,t) -#define STRUCT_PACK_DOARG28(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG27(s,f,__VA_ARGS__)) s f(27,t) -#define STRUCT_PACK_DOARG29(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG28(s,f,__VA_ARGS__)) s f(28,t) -#define STRUCT_PACK_DOARG30(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG29(s,f,__VA_ARGS__)) s f(29,t) -#define STRUCT_PACK_DOARG31(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG30(s,f,__VA_ARGS__)) s f(30,t) -#define STRUCT_PACK_DOARG32(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG31(s,f,__VA_ARGS__)) s f(31,t) -#define STRUCT_PACK_DOARG33(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG32(s,f,__VA_ARGS__)) s f(32,t) -#define STRUCT_PACK_DOARG34(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG33(s,f,__VA_ARGS__)) s f(33,t) -#define STRUCT_PACK_DOARG35(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG34(s,f,__VA_ARGS__)) s f(34,t) -#define STRUCT_PACK_DOARG36(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG35(s,f,__VA_ARGS__)) s f(35,t) -#define STRUCT_PACK_DOARG37(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG36(s,f,__VA_ARGS__)) s f(36,t) -#define STRUCT_PACK_DOARG38(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG37(s,f,__VA_ARGS__)) s f(37,t) -#define STRUCT_PACK_DOARG39(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG38(s,f,__VA_ARGS__)) s f(38,t) -#define STRUCT_PACK_DOARG40(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG39(s,f,__VA_ARGS__)) s f(39,t) -#define STRUCT_PACK_DOARG41(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG40(s,f,__VA_ARGS__)) s f(40,t) -#define STRUCT_PACK_DOARG42(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG41(s,f,__VA_ARGS__)) s f(41,t) -#define STRUCT_PACK_DOARG43(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG42(s,f,__VA_ARGS__)) s f(42,t) -#define STRUCT_PACK_DOARG44(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG43(s,f,__VA_ARGS__)) s f(43,t) -#define STRUCT_PACK_DOARG45(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG44(s,f,__VA_ARGS__)) s f(44,t) -#define STRUCT_PACK_DOARG46(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG45(s,f,__VA_ARGS__)) s f(45,t) -#define STRUCT_PACK_DOARG47(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG46(s,f,__VA_ARGS__)) s f(46,t) -#define STRUCT_PACK_DOARG48(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG47(s,f,__VA_ARGS__)) s f(47,t) -#define STRUCT_PACK_DOARG49(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG48(s,f,__VA_ARGS__)) s f(48,t) -#define STRUCT_PACK_DOARG50(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG49(s,f,__VA_ARGS__)) s f(49,t) -#define STRUCT_PACK_DOARG51(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG50(s,f,__VA_ARGS__)) s f(50,t) -#define STRUCT_PACK_DOARG52(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG51(s,f,__VA_ARGS__)) s f(51,t) -#define STRUCT_PACK_DOARG53(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG52(s,f,__VA_ARGS__)) s f(52,t) -#define STRUCT_PACK_DOARG54(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG53(s,f,__VA_ARGS__)) s f(53,t) -#define STRUCT_PACK_DOARG55(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG54(s,f,__VA_ARGS__)) s f(54,t) -#define STRUCT_PACK_DOARG56(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG55(s,f,__VA_ARGS__)) s f(55,t) -#define STRUCT_PACK_DOARG57(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG56(s,f,__VA_ARGS__)) s f(56,t) -#define STRUCT_PACK_DOARG58(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG57(s,f,__VA_ARGS__)) s f(57,t) -#define STRUCT_PACK_DOARG59(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG58(s,f,__VA_ARGS__)) s f(58,t) -#define STRUCT_PACK_DOARG60(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG59(s,f,__VA_ARGS__)) s f(59,t) -#define STRUCT_PACK_DOARG61(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG60(s,f,__VA_ARGS__)) s f(60,t) -#define STRUCT_PACK_DOARG62(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG61(s,f,__VA_ARGS__)) s f(61,t) -#define STRUCT_PACK_DOARG63(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG62(s,f,__VA_ARGS__)) s f(62,t) -#define STRUCT_PACK_DOARG64(s,f,t,...) STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_DOARG63(s,f,__VA_ARGS__)) s f(63,t) - -#define STRUCT_PACK_MAKE_ARGS0(Type) -#define STRUCT_PACK_MAKE_ARGS1(Type) Type -#define STRUCT_PACK_MAKE_ARGS2(Type) STRUCT_PACK_MAKE_ARGS1(Type), Type -#define STRUCT_PACK_MAKE_ARGS3(Type) STRUCT_PACK_MAKE_ARGS2(Type), Type -#define STRUCT_PACK_MAKE_ARGS4(Type) STRUCT_PACK_MAKE_ARGS3(Type), Type -#define STRUCT_PACK_MAKE_ARGS5(Type) STRUCT_PACK_MAKE_ARGS4(Type), Type -#define STRUCT_PACK_MAKE_ARGS6(Type) STRUCT_PACK_MAKE_ARGS5(Type), Type -#define STRUCT_PACK_MAKE_ARGS7(Type) STRUCT_PACK_MAKE_ARGS6(Type), Type -#define STRUCT_PACK_MAKE_ARGS8(Type) STRUCT_PACK_MAKE_ARGS7(Type), Type -#define STRUCT_PACK_MAKE_ARGS9(Type) STRUCT_PACK_MAKE_ARGS8(Type), Type -#define STRUCT_PACK_MAKE_ARGS10(Type) STRUCT_PACK_MAKE_ARGS9(Type), Type -#define STRUCT_PACK_MAKE_ARGS11(Type) STRUCT_PACK_MAKE_ARGS10(Type), Type -#define STRUCT_PACK_MAKE_ARGS12(Type) STRUCT_PACK_MAKE_ARGS11(Type), Type -#define STRUCT_PACK_MAKE_ARGS13(Type) STRUCT_PACK_MAKE_ARGS12(Type), Type -#define STRUCT_PACK_MAKE_ARGS14(Type) STRUCT_PACK_MAKE_ARGS13(Type), Type -#define STRUCT_PACK_MAKE_ARGS15(Type) STRUCT_PACK_MAKE_ARGS14(Type), Type -#define STRUCT_PACK_MAKE_ARGS16(Type) STRUCT_PACK_MAKE_ARGS15(Type), Type -#define STRUCT_PACK_MAKE_ARGS17(Type) STRUCT_PACK_MAKE_ARGS16(Type), Type -#define STRUCT_PACK_MAKE_ARGS18(Type) STRUCT_PACK_MAKE_ARGS17(Type), Type -#define STRUCT_PACK_MAKE_ARGS19(Type) STRUCT_PACK_MAKE_ARGS18(Type), Type -#define STRUCT_PACK_MAKE_ARGS20(Type) STRUCT_PACK_MAKE_ARGS19(Type), Type -#define STRUCT_PACK_MAKE_ARGS21(Type) STRUCT_PACK_MAKE_ARGS20(Type), Type -#define STRUCT_PACK_MAKE_ARGS22(Type) STRUCT_PACK_MAKE_ARGS21(Type), Type -#define STRUCT_PACK_MAKE_ARGS23(Type) STRUCT_PACK_MAKE_ARGS22(Type), Type -#define STRUCT_PACK_MAKE_ARGS24(Type) STRUCT_PACK_MAKE_ARGS23(Type), Type -#define STRUCT_PACK_MAKE_ARGS25(Type) STRUCT_PACK_MAKE_ARGS24(Type), Type -#define STRUCT_PACK_MAKE_ARGS26(Type) STRUCT_PACK_MAKE_ARGS25(Type), Type -#define STRUCT_PACK_MAKE_ARGS27(Type) STRUCT_PACK_MAKE_ARGS26(Type), Type -#define STRUCT_PACK_MAKE_ARGS28(Type) STRUCT_PACK_MAKE_ARGS27(Type), Type -#define STRUCT_PACK_MAKE_ARGS29(Type) STRUCT_PACK_MAKE_ARGS28(Type), Type -#define STRUCT_PACK_MAKE_ARGS30(Type) STRUCT_PACK_MAKE_ARGS29(Type), Type -#define STRUCT_PACK_MAKE_ARGS31(Type) STRUCT_PACK_MAKE_ARGS30(Type), Type -#define STRUCT_PACK_MAKE_ARGS32(Type) STRUCT_PACK_MAKE_ARGS31(Type), Type -#define STRUCT_PACK_MAKE_ARGS33(Type) STRUCT_PACK_MAKE_ARGS32(Type), Type -#define STRUCT_PACK_MAKE_ARGS34(Type) STRUCT_PACK_MAKE_ARGS33(Type), Type -#define STRUCT_PACK_MAKE_ARGS35(Type) STRUCT_PACK_MAKE_ARGS34(Type), Type -#define STRUCT_PACK_MAKE_ARGS36(Type) STRUCT_PACK_MAKE_ARGS35(Type), Type -#define STRUCT_PACK_MAKE_ARGS37(Type) STRUCT_PACK_MAKE_ARGS36(Type), Type -#define STRUCT_PACK_MAKE_ARGS38(Type) STRUCT_PACK_MAKE_ARGS37(Type), Type -#define STRUCT_PACK_MAKE_ARGS39(Type) STRUCT_PACK_MAKE_ARGS38(Type), Type -#define STRUCT_PACK_MAKE_ARGS40(Type) STRUCT_PACK_MAKE_ARGS39(Type), Type -#define STRUCT_PACK_MAKE_ARGS41(Type) STRUCT_PACK_MAKE_ARGS40(Type), Type -#define STRUCT_PACK_MAKE_ARGS42(Type) STRUCT_PACK_MAKE_ARGS41(Type), Type -#define STRUCT_PACK_MAKE_ARGS43(Type) STRUCT_PACK_MAKE_ARGS42(Type), Type -#define STRUCT_PACK_MAKE_ARGS44(Type) STRUCT_PACK_MAKE_ARGS43(Type), Type -#define STRUCT_PACK_MAKE_ARGS45(Type) STRUCT_PACK_MAKE_ARGS44(Type), Type -#define STRUCT_PACK_MAKE_ARGS46(Type) STRUCT_PACK_MAKE_ARGS45(Type), Type -#define STRUCT_PACK_MAKE_ARGS47(Type) STRUCT_PACK_MAKE_ARGS46(Type), Type -#define STRUCT_PACK_MAKE_ARGS48(Type) STRUCT_PACK_MAKE_ARGS47(Type), Type -#define STRUCT_PACK_MAKE_ARGS49(Type) STRUCT_PACK_MAKE_ARGS48(Type), Type -#define STRUCT_PACK_MAKE_ARGS50(Type) STRUCT_PACK_MAKE_ARGS49(Type), Type -#define STRUCT_PACK_MAKE_ARGS51(Type) STRUCT_PACK_MAKE_ARGS50(Type), Type -#define STRUCT_PACK_MAKE_ARGS52(Type) STRUCT_PACK_MAKE_ARGS51(Type), Type -#define STRUCT_PACK_MAKE_ARGS53(Type) STRUCT_PACK_MAKE_ARGS52(Type), Type -#define STRUCT_PACK_MAKE_ARGS54(Type) STRUCT_PACK_MAKE_ARGS53(Type), Type -#define STRUCT_PACK_MAKE_ARGS55(Type) STRUCT_PACK_MAKE_ARGS54(Type), Type -#define STRUCT_PACK_MAKE_ARGS56(Type) STRUCT_PACK_MAKE_ARGS55(Type), Type -#define STRUCT_PACK_MAKE_ARGS57(Type) STRUCT_PACK_MAKE_ARGS56(Type), Type -#define STRUCT_PACK_MAKE_ARGS58(Type) STRUCT_PACK_MAKE_ARGS57(Type), Type -#define STRUCT_PACK_MAKE_ARGS59(Type) STRUCT_PACK_MAKE_ARGS58(Type), Type -#define STRUCT_PACK_MAKE_ARGS60(Type) STRUCT_PACK_MAKE_ARGS59(Type), Type -#define STRUCT_PACK_MAKE_ARGS61(Type) STRUCT_PACK_MAKE_ARGS60(Type), Type -#define STRUCT_PACK_MAKE_ARGS62(Type) STRUCT_PACK_MAKE_ARGS61(Type), Type -#define STRUCT_PACK_MAKE_ARGS63(Type) STRUCT_PACK_MAKE_ARGS62(Type), Type -#define STRUCT_PACK_MAKE_ARGS64(Type) STRUCT_PACK_MAKE_ARGS63(Type), Type - - -#define STRUCT_PACK_MAKE_ARGS(Type,Count) \ - STRUCT_PACK_CONCAT(STRUCT_PACK_MAKE_ARGS,Count)(Type) - -#define STRUCT_PACK_EXPAND_EACH_(sepatator,fun,...) \ - STRUCT_PACK_MARCO_EXPAND(STRUCT_PACK_CONCAT(STRUCT_PACK_DOARG,STRUCT_PACK_ARG_COUNT(__VA_ARGS__))(sepatator,fun,__VA_ARGS__)) -#define STRUCT_PACK_EXPAND_EACH(sepatator,fun,...) \ - STRUCT_PACK_EXPAND_EACH_(sepatator,fun,__VA_ARGS__) + #define STRUCT_PACK_RETURN_ELEMENT(Idx, X) \ if constexpr (Idx == I) {\ diff --git a/include/ylt/struct_pack/size_info.hpp b/include/ylt/struct_pack/size_info.hpp new file mode 100644 index 000000000..eb84acfc8 --- /dev/null +++ b/include/ylt/struct_pack/size_info.hpp @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2023, Alibaba Group Holding Limited; + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once +#include +struct size_info { + std::size_t total; + std::size_t size_cnt; + std::size_t max_size; + constexpr size_info &operator+=(const size_info &other) { + this->total += other.total; + this->size_cnt += other.size_cnt; + this->max_size = (std::max)(this->max_size, other.max_size); + return *this; + } + constexpr size_info operator+(const size_info &other) { + return {this->total + other.total, this->size_cnt += other.size_cnt, + (std::max)(this->max_size, other.max_size)}; + } +}; \ No newline at end of file diff --git a/include/ylt/struct_pack/struct_pack_impl.hpp b/include/ylt/struct_pack/struct_pack_impl.hpp index b74d8fe29..7e06765c9 100644 --- a/include/ylt/struct_pack/struct_pack_impl.hpp +++ b/include/ylt/struct_pack/struct_pack_impl.hpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -34,12 +35,12 @@ #include #include +#include "derived_helper.hpp" #include "error_code.hpp" #include "md5_constexpr.hpp" #include "reflection.hpp" #include "trivial_view.hpp" #include "varint.hpp" -#include "ylt/struct_pack.hpp" #if __cplusplus >= 202002L #include "tuple.hpp" @@ -339,6 +340,7 @@ enum class type_id { variant_t, expected_t, bitset_t, + unique_derived_class_t, // monostate, or void monostate_t = 250, // circle_flag @@ -541,7 +543,7 @@ constexpr type_id get_type_id() { return get_varint_type(); } else if constexpr (std::is_same_v || - std::is_same_v) { + std::is_same_v || std::is_abstract_v) { return type_id::monostate_t; } else if constexpr (bitset) { @@ -562,9 +564,17 @@ constexpr type_id get_type_id() { else if constexpr (container) { return type_id::container_t; } - else if constexpr (optional || unique_ptr) { + else if constexpr (optional) { return type_id::optional_t; } + else if constexpr (unique_ptr) { + if constexpr (is_base_class) { + return type_id::unique_derived_class_t; + } + else { + return type_id::optional_t; + } + } else if constexpr (is_variant_v) { static_assert( std::variant_size_v > 1 || @@ -701,21 +711,6 @@ std::size_t constexpr get_array_size() { } } -struct size_info { - std::size_t total; - std::size_t size_cnt; - std::size_t max_size; - constexpr size_info &operator+=(const size_info &other) { - this->total += other.total; - this->size_cnt += other.size_cnt; - this->max_size = (std::max)(this->max_size, other.max_size); - return *this; - } - constexpr size_info operator+(const size_info &other) { - return {this->total + other.total, this->size_cnt += other.size_cnt, - (std::max)(this->max_size, other.max_size)}; - } -}; template constexpr size_info inline calculate_one_size(const T &item); @@ -1135,8 +1130,15 @@ constexpr bool check_if_compatible_element_exist_impl_helper() { } else if constexpr (id == type_id::optional_t) { if constexpr (unique_ptr) { - return check_if_compatible_element_exist_impl_helper< - version, typename T::element_type, T, ParentArgs...>(); + if constexpr (is_base_class) { + return check_if_compatible_element_exist_impl< + version, derived_class_set_t, T, + ParentArgs...>(); + } + else { + return check_if_compatible_element_exist_impl_helper< + version, typename T::element_type, T, ParentArgs...>(); + } } else { return check_if_compatible_element_exist_impl_helper< @@ -1244,12 +1246,33 @@ constexpr size_info inline calculate_one_size(const T &item) { }, item); } - else if constexpr (optional || unique_ptr) { + else if constexpr (optional) { ret.total = sizeof(char); if (item) { ret += calculate_one_size(*item); } } + else if constexpr (unique_ptr) { + ret.total = sizeof(char); + if (item) { + if constexpr (is_base_class) { + ret.total += sizeof(uint32_t); + bool is_ok; + auto index = search_type_by_md5( + item->get_struct_pack_id(), is_ok); + if SP_UNLIKELY (!is_ok) { + throw std::runtime_error{ + "illegal struct_pack_id in virtual function."}; + } + ret += template_switch>>(index, + item.get()); + } + else { + ret += calculate_one_size(*item); + } + } + } else if constexpr (is_variant_v) { ret.total = sizeof(uint8_t); ret += std::visit( @@ -1368,8 +1391,15 @@ constexpr std::size_t calculate_compatible_version_size() { } else if constexpr (id == type_id::optional_t) { if constexpr (unique_ptr) { - sz = calculate_compatible_version_size(); + if constexpr (is_base_class) { + sz = calculate_compatible_version_size< + derived_class_set_t, T, + ParentArgs...>(); + } + else { + sz = calculate_compatible_version_size(); + } } else { sz = calculate_compatible_version_size) { - get_compatible_version_numbers(buffer, sz); + if constexpr (is_base_class) { + sz = get_compatible_version_numbers< + Buffer, derived_class_set_t, T, + ParentArgs...>(buffer, sz); + } + else { + get_compatible_version_numbers(buffer, sz); + } } else { get_compatible_version_numbers -constexpr void STRUCT_PACK_INLINE compile_time_sort(std::array &array) { - // FIXME: use faster compile-time sort - for (std::size_t i = 0; i < array.size(); ++i) { - for (std::size_t j = i + 1; j < array.size(); ++j) { - if (array[i] > array[j]) { - auto tmp = array[i]; - array[i] = array[j]; - array[j] = tmp; - } - } - } - return; -} - -template -constexpr std::size_t STRUCT_PACK_INLINE -calculate_uniqued_size(const std::array &input) { - std::size_t unique_cnt = sz; - for (std::size_t i = 1; i < input.size(); ++i) { - if (input[i] == input[i - 1]) { - --unique_cnt; - } - } - return unique_cnt; -} - -template -constexpr void STRUCT_PACK_INLINE compile_time_unique( - const std::array &input, std::array &output) { - std::size_t j = 0; - static_assert(sz1 != 0, "not allow empty input!"); - output[0] = input[0]; - for (std::size_t i = 1; i < input.size(); ++i) { - if (input[i] != input[i - 1]) { - output[++j] = input[i]; - } - } -} - template constexpr auto STRUCT_PACK_INLINE get_sorted_compatible_version_numbers() { std::array()> buffer{}; @@ -1658,6 +1655,9 @@ class packer { packer(const packer &) = delete; packer &operator=(const packer &) = delete; + template + friend struct serialize_one_derived_class_helper; + template void serialize_expand_compatible_helper(const T &t, std::index_sequence, @@ -1765,7 +1765,22 @@ class packer { bool has_value = (item != nullptr); writer_.write((char *)&has_value, sizeof(char)); if (has_value) { - serialize_one(*item); + if constexpr (is_base_class) { + bool is_ok; + uint32_t id = item->get_struct_pack_id(); + auto index = search_type_by_md5( + item->get_struct_pack_id(), is_ok); + assert(is_ok); + writer_.write((char *)&id, sizeof(uint32_t)); + template_switch, + std::integral_constant, + std::integral_constant>>(index, this, + item.get()); + } + else { + serialize_one(*item); + } } } else if constexpr (detail::varint_t) { @@ -1902,7 +1917,20 @@ class packer { } else if constexpr (unique_ptr) { if (item != nullptr) { - serialize_one(*item); + if constexpr (is_base_class) { + bool is_ok; + auto index = search_type_by_md5( + item->get_struct_pack_id(), is_ok); + assert(is_ok); + template_switch, + std::integral_constant, + std::integral_constant>>(index, this, + item.get()); + } + else { + serialize_one(*item); + } } } else if constexpr (id == type_id::array_t) { @@ -2052,6 +2080,10 @@ class unpacker { unpacker(const unpacker &) = delete; unpacker &operator=(const unpacker &) = delete; + template + friend struct deserialize_one_derived_class_helper; + STRUCT_PACK_INLINE unpacker(Reader &reader) : reader_(reader) { #if __cpp_concepts < 201907L static_assert(reader_t, @@ -2552,8 +2584,27 @@ class unpacker { if (!has_value) { return {}; } - item = std::make_unique(); - deserialize_one(*item); + if constexpr (is_base_class) { + uint32_t id; + reader_.read((char *)&id, sizeof(id)); + bool ok; + auto index = search_type_by_md5(id, ok); + if SP_UNLIKELY (!ok) { + return {}; + } + else { + return template_switch, + std::integral_constant, + std::integral_constant, + std::integral_constant>>(index, this, + item); + } + } + else { + item = std::make_unique(); + deserialize_one(*item); + } } else if constexpr (detail::varint_t) { code = detail::deserialize_varint(reader_, item); @@ -2838,7 +2889,21 @@ class unpacker { if (item == nullptr) { return {}; } - deserialize_one(*item); + if constexpr (is_base_class) { + uint32_t id = item->get_struct_pack_id(); + bool ok; + auto index = search_type_by_md5(id, ok); + assert(ok); + return template_switch, + std::integral_constant, + std::integral_constant, + std::integral_constant>>(index, this, + item); + } + else { + deserialize_one(*item); + } } else if constexpr (id == type_id::array_t) { for (auto &i : item) { @@ -2984,89 +3049,15 @@ class unpacker { unsigned char size_type_; }; -struct MD5_pair { - uint32_t md5; - uint32_t index; - constexpr friend bool operator<(const MD5_pair &l, const MD5_pair &r) { - return l.md5 < r.md5; - } - constexpr friend bool operator>(const MD5_pair &l, const MD5_pair &r) { - return l.md5 > r.md5; - } - constexpr friend bool operator==(const MD5_pair &l, const MD5_pair &r) { - return l.md5 == r.md5; - } -}; - -template -struct MD5_set { - static constexpr int size = sizeof...(DerivedClasses); - static_assert(size <= 256); - - private: - template - static constexpr std::array calculate_md5( - std::index_sequence) { - std::array md5{}; - ((md5[Index] = MD5_pair{get_types_code(), Index}), ...); - compile_time_sort(md5); - return md5; - } - static constexpr std::size_t has_hash_collision_impl() { - for (std::size_t i = 1; i < size; ++i) { - if (value[i - 1] == value[i]) { - return value[i].index; - } - } - return 0; - } - - public: - static constexpr std::array value = - calculate_md5(std::make_index_sequence()); - static constexpr std::size_t has_hash_collision = has_hash_collision_impl(); -}; - -template -struct public_base_class_checker { - static_assert(std::tuple_size_v <= 256); - - private: - template - static constexpr bool calculate_md5(std::index_sequence) { - return (std::is_base_of_v> && - ...); - } - - public: - static constexpr bool value = public_base_class_checker::calculate_md5( - std::make_index_sequence>()); -}; - -template -struct deserialize_derived_class_helper { - template - static STRUCT_PACK_INLINE constexpr struct_pack::errc run( - std::unique_ptr &base, unpack &unpacker) { - if constexpr (index >= std::tuple_size_v) { - unreachable(); - return struct_pack::errc{}; - } - else { - using derived_class = std::tuple_element_t; - base = std::make_unique(); - return unpacker.deserialize(*(derived_class *)base.get()); - } - } -}; - template struct MD5_reader_wrapper : public Reader { MD5_reader_wrapper(Reader &&reader) : Reader(std::move(reader)) { is_failed = !Reader::read((char *)&head_chars, sizeof(head_chars)); } bool read_head(char *target) { + if SP_UNLIKELY (is_failed) { + return false; + } memcpy(target, &head_chars, sizeof(head_chars)); return true; } @@ -3087,8 +3078,7 @@ template return struct_pack::errc::no_buffer_space; } unpacker> unpack{wrapper}; - constexpr auto &MD5s = MD5_set::value; - static_assert(MD5s.size() == sizeof...(DerivedClasses)); + constexpr auto &MD5s = MD5_set>::value; MD5_pair md5_pair{wrapper.get_md5(), 0}; auto result = std::lower_bound(MD5s.begin(), MD5s.end(), md5_pair); if (result == MD5s.end() || result->md5 != md5_pair.md5) { diff --git a/include/ylt/struct_pack/util.h b/include/ylt/struct_pack/util.h new file mode 100644 index 000000000..821e1032b --- /dev/null +++ b/include/ylt/struct_pack/util.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023, Alibaba Group Holding Limited; + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once +#include + +#include "marco.h" +namespace struct_pack::detail { +[[noreturn]] inline void unreachable() { + // Uses compiler specific extensions if possible. + // Even if no extension is used, undefined behavior is still raised by + // an empty function body and the noreturn attribute. +#ifdef __GNUC__ // GCC, Clang, ICC + __builtin_unreachable(); +#elif defined(_MSC_VER) // msvc + __assume(false); +#endif +} + +template +[[noreturn]] constexpr T declval() { + unreachable(); +} + +template +constexpr void STRUCT_PACK_INLINE compile_time_sort(std::array &array) { + // FIXME: use faster compile-time sort + for (std::size_t i = 0; i < array.size(); ++i) { + for (std::size_t j = i + 1; j < array.size(); ++j) { + if (array[i] > array[j]) { + auto tmp = array[i]; + array[i] = array[j]; + array[j] = tmp; + } + } + } + return; +} + +template +constexpr std::size_t STRUCT_PACK_INLINE +calculate_uniqued_size(const std::array &input) { + std::size_t unique_cnt = sz; + for (std::size_t i = 1; i < input.size(); ++i) { + if (input[i] == input[i - 1]) { + --unique_cnt; + } + } + return unique_cnt; +} + +template +constexpr void STRUCT_PACK_INLINE compile_time_unique( + const std::array &input, std::array &output) { + std::size_t j = 0; + static_assert(sz1 != 0, "not allow empty input!"); + output[0] = input[0]; + for (std::size_t i = 1; i < input.size(); ++i) { + if (input[i] != input[i - 1]) { + output[++j] = input[i]; + } + } +} +} // namespace struct_pack::detail \ No newline at end of file diff --git a/src/struct_pack/tests/test_derived.cpp b/src/struct_pack/tests/test_derived.cpp index 89c4aa758..4012db48c 100644 --- a/src/struct_pack/tests/test_derived.cpp +++ b/src/struct_pack/tests/test_derived.cpp @@ -1,84 +1,83 @@ -#include -#include -#include -#include - -#include "doctest.h" -#include "ylt/struct_pack.hpp" -#include "ylt/struct_pack/struct_pack_impl.hpp" +#include "test_derived.h" +namespace test1 { struct Base { + int id = 17; Base(){}; static struct_pack::expected, struct_pack::errc> deserialize(std::string_view sv); - virtual std::string get_name() const = 0; + virtual std::string get_name() const { return "Base"; }; + friend bool operator==(const Base& a, const Base& b) { return a.id == b.id; } virtual ~Base(){}; }; +STRUCT_PACK_REFL(Base, id); struct foo : public Base { std::string hello = "1"; std::string hi = "2"; virtual std::string get_name() const override { return "foo"; } friend bool operator==(const foo& a, const foo& b) { - return a.hello == b.hello && a.hi == b.hi; + return a.id == b.id && a.hello == b.hello && a.hi == b.hi; } }; -STRUCT_PACK_REFL(foo, hello, hi); +STRUCT_PACK_REFL(foo, id, hello, hi); struct foo2 : public Base { std::string hello = "1"; std::string hi = "2"; virtual std::string get_name() const override { return "foo2"; } friend bool operator==(const foo2& a, const foo2& b) { - return a.hello == b.hello && a.hi == b.hi; + return a.id == b.id && a.hello == b.hello && a.hi == b.hi; } static constexpr uint64_t struct_pack_id = 114514; }; -STRUCT_PACK_REFL(foo2, hello, hi); +STRUCT_PACK_REFL(foo2, id, hello, hi); struct foo3 : public Base { std::string hello = "1"; std::string hi = "2"; virtual std::string get_name() const override { return "foo3"; } friend bool operator==(const foo3& a, const foo3& b) { - return a.hello == b.hello && a.hi == b.hi; + return a.id == b.id && a.hello == b.hello && a.hi == b.hi; } }; -STRUCT_PACK_REFL(foo3, hello, hi); +STRUCT_PACK_REFL(foo3, id, hello, hi); struct foo4 : public Base { std::string hello = "1"; std::string hi = "2"; virtual std::string get_name() const override { return "foo4"; } friend bool operator==(const foo4& a, const foo4& b) { - return a.hello == b.hello && a.hi == b.hi; + return a.id == b.id && a.hello == b.hello && a.hi == b.hi; } }; constexpr int struct_pack_id(foo4*) { return 112233211; } -STRUCT_PACK_REFL(foo4, hello, hi); +STRUCT_PACK_REFL(foo4, id, hello, hi); struct bar : public Base { int oh = 1; int no = 2; virtual std::string get_name() const override { return "bar"; } friend bool operator==(const bar& a, const bar& b) { - return a.oh == b.oh && a.no == b.no; + return a.id == b.id && a.oh == b.oh && a.no == b.no; } }; -STRUCT_PACK_REFL(bar, oh, no); +STRUCT_PACK_REFL(bar, id, oh, no); struct gua : Base { std::string a = "Hello"; int b = 1; virtual std::string get_name() const override { return "gua"; } friend bool operator==(const gua& a, const gua& b) { - return a.a == b.a && a.b == b.b; + return a.id == b.id && a.a == b.a && a.b == b.b; } }; -STRUCT_PACK_REFL(gua, a, b); +STRUCT_PACK_REFL(gua, id, a, b); struct_pack::expected, struct_pack::errc> Base::deserialize(std::string_view sv) { - return struct_pack::deserialize_derived_class(sv); } - +} // namespace test1 TEST_CASE("testing derived") { using namespace std::string_literals; + using namespace test1; static_assert(struct_pack::detail::has_user_defined_id_ADL); + Base base; foo f; foo2 f2; foo4 f4; @@ -88,28 +87,76 @@ TEST_CASE("testing derived") { struct_pack::serialize(b), struct_pack::serialize(g), struct_pack::serialize(f2), - struct_pack::serialize(f4)}; + struct_pack::serialize(f4), + struct_pack::serialize(base)}; auto f1 = Base::deserialize(vecs[0]); auto b1 = Base::deserialize(vecs[1]); auto g1 = Base::deserialize(vecs[2]); auto f21 = Base::deserialize(vecs[3]); auto f41 = Base::deserialize(vecs[4]); + auto base1 = Base::deserialize(vecs[5]); CHECK(*(foo*)(f1->get()) == f); CHECK(*(foo2*)(f21->get()) == f2); CHECK(*(bar*)(b1->get()) == b); CHECK(*(gua*)(g1->get()) == g); + CHECK(*(base1->get()) == base); std::vector, std::string>> vec; vec.emplace_back(std::move(f1.value()), "foo"); vec.emplace_back(std::move(f21.value()), "foo2"); vec.emplace_back(std::move(b1.value()), "bar"); vec.emplace_back(std::move(g1.value()), "gua"); vec.emplace_back(std::move(f41.value()), "foo4"); + vec.emplace_back(std::move(base1.value()), "Base"); for (const auto& e : vec) { CHECK(e.first->get_name() == e.second); } } TEST_CASE("test hash collision") { - static_assert(struct_pack::detail::MD5_set::has_hash_collision != 0); + using namespace test1; + static_assert( + struct_pack::detail::MD5_set< + std::tuple>::has_hash_collision != + 0); +} + + +TEST_CASE("test unique_ptr") { + using namespace test2; + static_assert(struct_pack::detail::is_base_class); + std::vector> vec; + vec.emplace_back(std::make_unique()); + vec.emplace_back(std::make_unique()); + vec.emplace_back(std::make_unique()); + vec.emplace_back(std::make_unique()); + vec.emplace_back(std::make_unique()); + auto buffer = struct_pack::serialize(vec); + auto res = + struct_pack::deserialize>>(buffer); + CHECK(res); + auto& vec2 = res.value(); + CHECK(vec2.size() == vec.size()); + for (std::size_t i = 0; i < vec.size(); ++i) { + CHECK(vec[i]->get_name() == vec2[i]->get_name()); + } +} + + +TEST_CASE("test unique_ptr with virtual base") { + using namespace test3; + static_assert(struct_pack::detail::is_base_class); + std::vector> vec; + vec.emplace_back(std::make_unique()); + vec.emplace_back(std::make_unique()); + vec.emplace_back(std::make_unique()); + vec.emplace_back(std::make_unique()); + auto buffer = struct_pack::serialize(vec); + auto res = + struct_pack::deserialize>>(buffer); + CHECK(res); + auto& vec2 = res.value(); + CHECK(vec2.size() == vec.size()); + for (std::size_t i = 0; i < vec.size(); ++i) { + CHECK(vec[i]->get_name() == vec2[i]->get_name()); + } } \ No newline at end of file diff --git a/src/struct_pack/tests/test_derived.h b/src/struct_pack/tests/test_derived.h new file mode 100644 index 000000000..eecb7ce86 --- /dev/null +++ b/src/struct_pack/tests/test_derived.h @@ -0,0 +1,101 @@ +#include +#include +#include +#include + +#include "doctest.h" +#include "ylt/struct_pack.hpp" +#include "ylt/struct_pack/derived_helper.hpp" +#include "ylt/struct_pack/derived_marco.hpp" +#include "ylt/struct_pack/struct_pack_impl.hpp" +#include "ylt/struct_pack/util.h" +namespace test2 { + +struct base { + virtual uint32_t get_struct_pack_id() const; + virtual std::string get_name() const { return std::to_string(a); } + int a = 1; + virtual ~base(){}; +}; +STRUCT_PACK_REFL(base, a); + +struct derived1 : public base { + virtual uint32_t get_struct_pack_id() const; + virtual std::string get_name() const { + return base::get_name() + std::to_string(b); + } + int b = 2; +}; + +STRUCT_PACK_REFL(derived1, a, b); +struct derived2 : public base { + virtual uint32_t get_struct_pack_id() const; + virtual std::string get_name() const { return base::get_name() + c; } + std::string c = "Hello"; +}; + +STRUCT_PACK_REFL(derived2, a, c); +struct derived3 : public base { + virtual uint32_t get_struct_pack_id() const; + virtual std::string get_name() const { return base::get_name() + d; } + std::string d = "Oh no"; + static constexpr std::size_t struct_pack_id = 0; +}; +STRUCT_PACK_REFL(derived3, a, d); +struct derived4 : public derived3 { + virtual uint32_t get_struct_pack_id() const; + virtual std::string get_name() const { return derived3::get_name() + e; } + std::string e = "!"; +}; + +STRUCT_PACK_REFL(derived4, a, d, e); + +STRUCT_PACK_DERIVED_DECL(base, derived1, derived2, derived3, derived4); +} // namespace test2 +namespace test3 { + +struct base { + virtual uint32_t get_struct_pack_id() const = 0; + virtual std::string get_name() const = 0; + int a = 1; + virtual ~base(){}; +}; + +inline std::string base::get_name() const { return std::to_string(a); } + +struct derived1 : public base { + virtual uint32_t get_struct_pack_id() const; + virtual std::string get_name() const { + return base::get_name() + std::to_string(b); + } + int b = 2; +}; + +STRUCT_PACK_REFL(derived1, a, b); +struct derived2 : public base { + virtual uint32_t get_struct_pack_id() const; + virtual std::string get_name() const { return base::get_name() + c; } + std::string c = "Hello"; +}; + +STRUCT_PACK_REFL(derived2, a, c); +struct derived3 : public base { + virtual uint32_t get_struct_pack_id() const; + virtual std::string get_name() const { return base::get_name() + d; } + std::string d = "Oh no"; + static constexpr std::size_t struct_pack_id = 0; +}; + +STRUCT_PACK_REFL(derived3, a, d); + +struct derived4 : public derived3 { + virtual uint32_t get_struct_pack_id() const; + virtual std::string get_name() const { return derived3::get_name() + e; } + std::string e = "!"; +}; + +STRUCT_PACK_REFL(derived4, a, d, e); + +STRUCT_PACK_DERIVED_DECL(base, derived1, derived2, derived3, derived4); + +} // namespace test3 \ No newline at end of file