From 97b98d7b338ce06b626882b46508a83260e03291 Mon Sep 17 00:00:00 2001 From: saipubw Date: Tue, 19 Sep 2023 17:02:36 +0800 Subject: [PATCH] [struct_pack] remove concept of trivial_class_t/non_trivial_class_t (#461) --- include/ylt/struct_pack/struct_pack_impl.hpp | 27 ++++------ .../tests/test_compile_time_calculate.cpp | 23 +++++--- src/struct_pack/tests/test_data_struct.cpp | 34 ++++++------ src/struct_pack/tests/test_serialize.cpp | 25 +++++++-- .../en/struct_pack/struct_pack_type_system.md | 46 ++-------------- .../zh/struct_pack/struct_pack_type_system.md | 53 ++----------------- 6 files changed, 69 insertions(+), 139 deletions(-) diff --git a/include/ylt/struct_pack/struct_pack_impl.hpp b/include/ylt/struct_pack/struct_pack_impl.hpp index 005068f8f..4ee26a731 100644 --- a/include/ylt/struct_pack/struct_pack_impl.hpp +++ b/include/ylt/struct_pack/struct_pack_impl.hpp @@ -345,9 +345,8 @@ enum class type_id { circle_flag = 251, // end helper with user defined type ID type_end_flag_with_id = 252, - trivial_class_t = 253, - // struct type - non_trivial_class_t = 254, + // class type + struct_t = 253, // end helper type_end_flag = 255, }; @@ -579,13 +578,10 @@ constexpr type_id get_type_id() { return type_id::expected_t; } else if constexpr (is_trivial_tuple || pair) { - return type_id::trivial_class_t; - } - else if constexpr (tuple) { - return type_id::non_trivial_class_t; + return type_id::struct_t; } else if constexpr (std::is_class_v) { - return type_id::trivial_class_t; + return type_id::struct_t; } else { static_assert(!sizeof(T), "not supported type"); @@ -952,8 +948,7 @@ constexpr decltype(auto) get_type_literal() { else { constexpr auto id = get_type_id(); constexpr auto begin = string_literal{{static_cast(id)}}; - if constexpr (id == type_id::non_trivial_class_t || - id == type_id::trivial_class_t) { + if constexpr (id == type_id::struct_t) { using Args = decltype(get_types()); constexpr auto end = get_type_end_flag(); constexpr auto body = get_type_literal( @@ -1063,8 +1058,7 @@ constexpr decltype(auto) get_types_literal() { } else { constexpr auto root_id = get_type_id>(); - if constexpr (root_id == type_id::non_trivial_class_t || - root_id == type_id::trivial_class_t) { + if constexpr (root_id == type_id::struct_t) { constexpr auto end = get_type_end_flag>(); constexpr auto begin = string_literal{{static_cast(root_id)}}; @@ -1133,8 +1127,7 @@ constexpr bool check_if_compatible_element_exist_impl_helper() { return true; } else { - if constexpr (id == type_id::non_trivial_class_t || - id == type_id::trivial_class_t) { + if constexpr (id == type_id::struct_t) { using subArgs = decltype(get_types()); return check_if_compatible_element_exist_impl( @@ -1367,8 +1360,7 @@ constexpr std::size_t calculate_compatible_version_size() { sz = 1; } else { - if constexpr (id == type_id::non_trivial_class_t || - id == type_id::trivial_class_t) { + if constexpr (id == type_id::struct_t) { using subArgs = decltype(get_types()); return calculate_compatible_version_size( std::make_index_sequence>()); @@ -1452,8 +1444,7 @@ constexpr void get_compatible_version_numbers(Buffer &buffer, std::size_t &sz) { return; } else { - if constexpr (id == type_id::non_trivial_class_t || - id == type_id::trivial_class_t) { + if constexpr (id == type_id::struct_t) { using subArgs = decltype(get_types()); get_compatible_version_numbers( buffer, sz, std::make_index_sequence>()); diff --git a/src/struct_pack/tests/test_compile_time_calculate.cpp b/src/struct_pack/tests/test_compile_time_calculate.cpp index 6d8de1737..268a808fe 100644 --- a/src/struct_pack/tests/test_compile_time_calculate.cpp +++ b/src/struct_pack/tests/test_compile_time_calculate.cpp @@ -285,18 +285,25 @@ TEST_CASE("type calculate") { serialize(tuplet::tuple{}))); } { - static_assert(get_type_code>() != + static_assert(get_type_code>() != + get_type_code>(), + "tuple is not trival copyable, we got different layout"); + CHECK(!deserialize>( + serialize(std::tuple{}))); + } + { + static_assert(get_type_code>() == get_type_code(), - "different class accord and trival_class" - "concept should get different MD5"); - CHECK(!deserialize>(serialize(person{}))); + "same type should " + "get same MD5"); + CHECK(deserialize>(serialize(person{}))); } { - static_assert(get_type_code>() != + static_assert(get_type_code>() == get_type_code>(), - "different class accord and trival_class concept should " - "get different MD5"); - CHECK(!deserialize>( + "same type should " + "get same MD5"); + CHECK(deserialize>( serialize(std::tuple{}))); } { diff --git a/src/struct_pack/tests/test_data_struct.cpp b/src/struct_pack/tests/test_data_struct.cpp index 0ea322ee8..384fdcc0c 100644 --- a/src/struct_pack/tests/test_data_struct.cpp +++ b/src/struct_pack/tests/test_data_struct.cpp @@ -516,11 +516,11 @@ TEST_CASE("test unique_ptr") { auto literal = struct_pack::get_type_literal(); std::string_view sv{literal.data(), literal.size()}; using struct_pack::detail::type_id; - CHECK(sv == - std::string{(char)type_id::trivial_class_t, (char)type_id::optional_t, - (char)type_id::circle_flag, (char)129, - (char)type_id::string_t, (char)type_id::char_8_t, - (char)type_id::int32_t, (char)type_id::type_end_flag}); + CHECK(sv == std::string{(char)type_id::struct_t, (char)type_id::optional_t, + (char)type_id::circle_flag, (char)129, + (char)type_id::string_t, (char)type_id::char_8_t, + (char)type_id::int32_t, + (char)type_id::type_end_flag}); CHECK(result == list_head); } SUBCASE("test list(unique_ptr)") { @@ -542,11 +542,11 @@ TEST_CASE("test unique_ptr") { auto literal = struct_pack::get_type_literal>(); std::string_view sv{literal.data(), literal.size()}; using struct_pack::detail::type_id; - CHECK(sv == - std::string{(char)type_id::optional_t, (char)type_id::trivial_class_t, - (char)type_id::circle_flag, (char)129, - (char)type_id::string_t, (char)type_id::char_8_t, - (char)type_id::int32_t, (char)type_id::type_end_flag}); + CHECK(sv == std::string{(char)type_id::optional_t, (char)type_id::struct_t, + (char)type_id::circle_flag, (char)129, + (char)type_id::string_t, (char)type_id::char_8_t, + (char)type_id::int32_t, + (char)type_id::type_end_flag}); CHECK(*result.value() == *result.value()); } SUBCASE("test list2") { @@ -568,12 +568,12 @@ TEST_CASE("test unique_ptr") { auto literal = struct_pack::get_type_literal>(); std::string_view sv{literal.data(), literal.size()}; using struct_pack::detail::type_id; - CHECK(sv == std::string{ - (char)type_id::optional_t, (char)type_id::trivial_class_t, - (char)type_id::trivial_class_t, (char)type_id::circle_flag, - (char)130, (char)type_id::string_t, (char)type_id::char_8_t, - (char)type_id::int32_t, (char)type_id::type_end_flag, - (char)type_id::type_end_flag}); + CHECK(sv == std::string{(char)type_id::optional_t, (char)type_id::struct_t, + (char)type_id::struct_t, (char)type_id::circle_flag, + (char)130, (char)type_id::string_t, + (char)type_id::char_8_t, (char)type_id::int32_t, + (char)type_id::type_end_flag, + (char)type_id::type_end_flag}); CHECK(*result.value() == *result.value()); } SUBCASE("test tree") { @@ -581,7 +581,7 @@ TEST_CASE("test unique_ptr") { auto sv = std::string_view{literal.data(), literal.size()}; using struct_pack::detail::type_id; CHECK(sv == std::string{ - (char)type_id::trivial_class_t, (char)type_id::optional_t, + (char)type_id::struct_t, (char)type_id::optional_t, (char)type_id::circle_flag, (char)129, (char)type_id::optional_t, (char)type_id::circle_flag, (char)129, (char)type_id::string_t, (char)type_id::char_8_t, diff --git a/src/struct_pack/tests/test_serialize.cpp b/src/struct_pack/tests/test_serialize.cpp index f2709d602..9941c8f79 100644 --- a/src/struct_pack/tests/test_serialize.cpp +++ b/src/struct_pack/tests/test_serialize.cpp @@ -199,8 +199,23 @@ TEST_CASE("testing exceptions") { CHECK(ret3.error() == struct_pack::errc::no_buffer_space); } } - -TEST_CASE("testing serialize/deserialize varadic params") { +using namespace std::string_literals; +TEST_CASE("testing serialize/deserialize variadic params") { + { + person p{24, "Betty"}; + auto buffer = struct_pack::serialize(p); + auto res = struct_pack::deserialize(buffer); + CHECK(res); + CHECK(std::get<0>(res.value()) == 24); + CHECK(std::get<1>(res.value()) == "Betty"); + } + { + person p{24, "Betty"}; + auto buffer = struct_pack::serialize(24, "Betty"s); + auto res = struct_pack::deserialize(buffer); + CHECK(res); + CHECK(res.value() == p); + } { auto ret = struct_pack::serialize(1, 2, 3, 4, 5); auto res = struct_pack::deserialize>( @@ -570,18 +585,18 @@ TEST_CASE("test get type code") { auto str = get_type_literal(); static_assert(str.size() == 5); string_literal val{ - {(char)-2, 1, 1, 7, (char)-1}}; //{'1','1','7'}; + {(char)-3, 1, 1, 7, (char)-1}}; //{'1','1','7'}; CHECK(str == val); auto str1 = get_type_literal(); static_assert(str1.size() == 4); - string_literal val1{{(char)-2, 3, 4, (char)-1}}; //{'3','4'}; + string_literal val1{{(char)-3, 3, 4, (char)-1}}; //{'3','4'}; CHECK(str1 == val1); auto str2 = get_type_literal>(); static_assert(str2.size() == 4); - string_literal val2{{(char)-2, 3, 4, (char)-1}}; + string_literal val2{{(char)-3, 3, 4, (char)-1}}; CHECK(str2 == val2); } } diff --git a/website/docs/en/struct_pack/struct_pack_type_system.md b/website/docs/en/struct_pack/struct_pack_type_system.md index 65e8b4b8b..3bcd91d92 100644 --- a/website/docs/en/struct_pack/struct_pack_type_system.md +++ b/website/docs/en/struct_pack/struct_pack_type_system.md @@ -216,48 +216,10 @@ The class needs to provide: `size()`,`flip()`,`set()`,`reset()`,`count()`,and th ## Struct -`struct_pack` supports `struct`. Up to **64** fields are supported and nested fields are supported too. All members -should be of valid `struct_pack` type. There are two kinds of `struct`: +`struct_pack` supports `struct` type. Up to **64** fields are supported and nested fields are supported too. All members +should be of valid `struct_pack` type. -### struct/class/std::pair/tuplet::tuple - -For example: - -```cpp -struct person { - int age; - std::string name; -}; -``` -and -```cpp -struct person2 { - std::string name; - int age; -}; -STRUCT_PACK_REFL(person2,age,name) -``` -and -```cpp -std::pair -``` -and -```cpp -tuplet::tuple -``` - -Those types are same type in struct_pack. - -### std::tuple - -For historical reasons, `std::tuple` have a different memory layout than ordinary structs, and for optimization reasons we distinguish them from ordinary structs in the type system. For example: - -For instance: - -```cpp -std::tuple -``` -are different types with `person` in struct_pack. +struct type could be `struct/class/std::tuple/tuplet::tuple/std::pair` ### trivial struct @@ -309,6 +271,8 @@ STRUCT_PACK_REFL(bar,a,b,c); static_assert(struct_pack::get_type_code()!=struct_pack::get_type_code()); ``` +the `std::tuple` is not trivial struct too. + ## Compatible Type This refers to `struct_pack::compatible`. This is a special data type kind of identical to `std::optional` in cpp. In `struct_pack` it is dedicated for the forward/backward compatibility purpose. diff --git a/website/docs/zh/struct_pack/struct_pack_type_system.md b/website/docs/zh/struct_pack/struct_pack_type_system.md index 526537f4f..6d3188c44 100644 --- a/website/docs/zh/struct_pack/struct_pack_type_system.md +++ b/website/docs/zh/struct_pack/struct_pack_type_system.md @@ -221,59 +221,11 @@ concept unique_ptr = requires(Type ptr) { struct_pack支持结构体类型。结构体内可以包含最多64个字段,并允许结构体嵌套。结构体中的任何成员都必须是struct_pack的合法类型。 -struct_pack将结构体分为两种: - -### struct/class/std::pair/tuplet::tuple - -例如: - -```cpp -struct person { - int age; - std::string name; -}; -``` -```cpp -struct person2 { - std::string name; - int age; -}; -STRUCT_PACK_REFL(person2,age,name) -``` -和 -```cpp -std::pair -``` -以及 -```cpp -tuplet::tuple -``` -在 struct_pack中被视作相同的类型。 - -### std::tuple - -由于历史原因,其内存布局和普通的struct不同,因此我们在类型系统中将其视作不同的类型。 - -例如: - -```cpp -struct person { - int age; - std::string name; -}; -``` - -和 - -```cpp -std::tuple -``` - -这两者是不同的类型。 +struct_pack的结构体类型可以为:struct/class/std::pair/tuplet::tuple/std::tuple ### 平凡结构体 -假如一个类型是`struct/class/std::pair/tuplet::tuple`,且其所有的成员字段都是平凡字段,并且该类型未使用`STRUCT_PACK_REFL`宏注册,则该类型被视为平凡结构体类型。 +假如一个结构体类型是`struct/class/std::pair/tuplet::tuple`,且其所有的成员字段都是平凡字段,并且该类型未使用`STRUCT_PACK_REFL`宏注册,则该结构体被视为平凡结构体类型。 平凡字段是下面几种类型中的一种: 1. 基本类型 @@ -320,6 +272,7 @@ STRUCT_PACK_REFL(bar,a,b,c); static_assert(struct_pack::get_type_code()!=struct_pack::get_type_code()); ``` +此外,std::tuple也一定不是平凡结构体。 ## 兼容类型