From b5ff1d46f9b2ad7d076098a9a4e1383869704781 Mon Sep 17 00:00:00 2001 From: eyalz800 Date: Mon, 8 May 2023 14:15:22 +0300 Subject: [PATCH] Array concept was not generalized enough to avoid treating as aggregate in endian aware case and not working well with self referencing concept. --- test/src/test_stdarray.cpp | 39 +++++++++++++++++++++++++++++++++++--- zpp_bits.h | 38 ++++++++++++++++++++----------------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/test/src/test_stdarray.cpp b/test/src/test_stdarray.cpp index bb25017..0741619 100644 --- a/test/src/test_stdarray.cpp +++ b/test/src/test_stdarray.cpp @@ -48,10 +48,10 @@ TEST(stdarray, string) TEST(stdarray, large_array) { auto [data, in, out] = zpp::bits::data_in_out(); - std::array a1 = {1,2,3,4}; + std::array a1 = {1,2,3,4}; out(a1).or_throw(); - std::array a2{}; + std::array a2{}; in(a2).or_throw(); for (std::size_t i = 0; i < std::extent_v; ++i) { @@ -64,7 +64,7 @@ TEST(stdarray, large_array_in_struct) auto [data, in, out] = zpp::bits::data_in_out(); struct a { - std::array a1 = {1,2,3,4}; + std::array a1 = {1,2,3,4}; }; a a1 = {1,2,3,4}; @@ -78,4 +78,37 @@ TEST(stdarray, large_array_in_struct) } } +TEST(stdarray, large_array_endian) +{ + auto [data, in, out] = + zpp::bits::data_in_out(zpp::bits::endian::swapped{}); + std::array a1 = {1, 2, 3, 4}; + out(a1).or_throw(); + + std::array a2{}; + in(a2).or_throw(); + + for (std::size_t i = 0; i < std::extent_v; ++i) { + EXPECT_EQ(a1[i], a2[i]); + } +} + +TEST(stdarray, large_array_in_struct_endian) +{ + auto [data, in, out] = + zpp::bits::data_in_out(zpp::bits::endian::swapped{}); + struct a + { + std::array a1 = {1,2,3,4}; + }; + + a a1 = {1,2,3,4}; + out(a1).or_throw(); + + a a2; + in(a2).or_throw(); + for (std::size_t i = 0; i < std::extent_v; ++i) { + EXPECT_EQ(a1.a1[i], a2.a1[i]); + } +} diff --git a/zpp_bits.h b/zpp_bits.h index 978ad6d..59f0e68 100644 --- a/zpp_bits.h +++ b/zpp_bits.h @@ -817,7 +817,7 @@ template concept by_protocol = has_protocol && !has_explicit_serialize; template -concept array = std::is_array_v>; +concept basic_array = std::is_array_v>; template concept unspecialized = @@ -891,6 +891,16 @@ concept has_fixed_nonzero_size = requires std::remove_cvref_t{}.size()>::value != 0; }; +template +concept array = + basic_array || + (container && has_fixed_nonzero_size && requires { + requires Type { + } + .size() * sizeof(typename Type::value_type) == sizeof(Type); + Type{}.data(); + }); + } // namespace concepts template @@ -1258,14 +1268,9 @@ constexpr auto access::byte_serializable() 0)>::value == 0; }) { return false; - } else if constexpr (concepts::container && - concepts::has_fixed_nonzero_size && - requires { - type{}.size() * sizeof(typename type::value_type) == - sizeof(type); - type{}.data(); - }) { - return byte_serializable(); + } else if constexpr (concepts::array) { + return byte_serializable< + std::remove_cvref_t()[0])>>(); } else if constexpr (members_count > 0) { return visit_members_types( byte_serializable_visitor{})(); @@ -1325,15 +1330,9 @@ constexpr auto access::endian_independent_byte_serializable() 0)>::value == 0; }) { return false; - } else if constexpr (concepts::container && - concepts::has_fixed_nonzero_size && - requires { - type{}.size() * sizeof(typename type::value_type) == - sizeof(type); - type{}.data(); - }) { + } else if constexpr (concepts::array) { return endian_independent_byte_serializable< - typename type::value_type>(); + std::remove_cvref_t()[0])>>(); } else if constexpr (members_count > 0) { return visit_members_types( endian_independent_byte_serializable_visitor{})(); @@ -1385,6 +1384,11 @@ constexpr auto access::self_referencing() return false; } else if constexpr (members_count == 0) { return false; + } else if constexpr (concepts::array) { + return self_referencing< + std::remove_cvref_t()[0])>, + self, + Visited...>(); } else { return visit_members_types( self_referencing_visitor{})();