From 35f93831ec4396e9d1108e64e32bf812b9c57ec3 Mon Sep 17 00:00:00 2001 From: enum-class Date: Sun, 1 Jan 2023 11:58:25 +0800 Subject: [PATCH 1/4] Fix operator==() generated for field of fixed sized array --- include/flatbuffers/array.h | 6 +++ src/idl_gen_cpp.cpp | 3 +- tests/arrays_test_generated.h | 12 ++--- tests/key_field/key_field_sample_generated.h | 4 +- tests/test.cpp | 49 ++++++++++++++++++++ 5 files changed, 65 insertions(+), 9 deletions(-) diff --git a/include/flatbuffers/array.h b/include/flatbuffers/array.h index ec34deea5a4..2227d08d2fb 100644 --- a/include/flatbuffers/array.h +++ b/include/flatbuffers/array.h @@ -238,6 +238,12 @@ const Array &CastToArrayOfEnum(const T (&arr)[length]) { return *reinterpret_cast *>(arr); } +template +bool operator==(const Array &lhs, const Array &rhs) { + return (lhs.size() == rhs.size() && + std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0); +} + } // namespace flatbuffers #endif // FLATBUFFERS_ARRAY_H_ diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 5b9e181eb12..4f6236fbc1c 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -2044,7 +2044,6 @@ class CppGenerator : public BaseGenerator { const auto accessor = Name(field) + accessSuffix; const auto lhs_accessor = "lhs." + accessor; const auto rhs_accessor = "rhs." + accessor; - if (!field.deprecated && // Deprecated fields won't be accessible. field.value.type.base_type != BASE_TYPE_UTYPE && (field.value.type.base_type != BASE_TYPE_VECTOR || @@ -2067,6 +2066,8 @@ class CppGenerator : public BaseGenerator { " const &b) { return (a == b) || (a && b && *a == *b); })"; compare_op += "(" + equal_length + " && " + elements_equal + ")"; + } else if (field.value.type.base_type == BASE_TYPE_ARRAY) { + compare_op += "(*" + lhs_accessor + " == *" + rhs_accessor + ")"; } else { compare_op += "(" + lhs_accessor + " == " + rhs_accessor + ")"; } diff --git a/tests/arrays_test_generated.h b/tests/arrays_test_generated.h index c89af369a06..434c727ec17 100644 --- a/tests/arrays_test_generated.h +++ b/tests/arrays_test_generated.h @@ -141,10 +141,10 @@ FLATBUFFERS_STRUCT_END(NestedStruct, 32); inline bool operator==(const NestedStruct &lhs, const NestedStruct &rhs) { return - (lhs.a() == rhs.a()) && + (*lhs.a() == *rhs.a()) && (lhs.b() == rhs.b()) && - (lhs.c() == rhs.c()) && - (lhs.d() == rhs.d()); + (*lhs.c() == *rhs.c()) && + (*lhs.d() == *rhs.d()); } inline bool operator!=(const NestedStruct &lhs, const NestedStruct &rhs) { @@ -257,11 +257,11 @@ FLATBUFFERS_STRUCT_END(ArrayStruct, 160); inline bool operator==(const ArrayStruct &lhs, const ArrayStruct &rhs) { return (lhs.a() == rhs.a()) && - (lhs.b() == rhs.b()) && + (*lhs.b() == *rhs.b()) && (lhs.c() == rhs.c()) && - (lhs.d() == rhs.d()) && + (*lhs.d() == *rhs.d()) && (lhs.e() == rhs.e()) && - (lhs.f() == rhs.f()); + (*lhs.f() == *rhs.f()); } inline bool operator!=(const ArrayStruct &lhs, const ArrayStruct &rhs) { diff --git a/tests/key_field/key_field_sample_generated.h b/tests/key_field/key_field_sample_generated.h index be16f65581d..74bd7489bf3 100644 --- a/tests/key_field/key_field_sample_generated.h +++ b/tests/key_field/key_field_sample_generated.h @@ -88,7 +88,7 @@ FLATBUFFERS_STRUCT_END(Baz, 5); inline bool operator==(const Baz &lhs, const Baz &rhs) { return - (lhs.a() == rhs.a()) && + (*lhs.a() == *rhs.a()) && (lhs.b() == rhs.b()); } @@ -161,7 +161,7 @@ FLATBUFFERS_STRUCT_END(Bar, 16); inline bool operator==(const Bar &lhs, const Bar &rhs) { return - (lhs.a() == rhs.a()) && + (*lhs.a() == *rhs.a()) && (lhs.b() == rhs.b()); } diff --git a/tests/test.cpp b/tests/test.cpp index e13bc6ee2eb..27f2c2bfc3a 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -829,6 +829,54 @@ void FixedLengthArrayConstructorTest() { void FixedLengthArrayConstructorTest() {} #endif +void FixedLengthArrayOpratorEqualTest() { + const int32_t nested_a[2] = { 1, 2 }; + MyGame::Example::TestEnum nested_c[2] = { MyGame::Example::TestEnum::A, + MyGame::Example::TestEnum::B }; + + MyGame::Example::TestEnum nested_cc[2] = { MyGame::Example::TestEnum::A, + MyGame::Example::TestEnum::C }; + const int64_t int64_2[2] = { -2, -1 }; + + std::array init_d = { + { MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B, + nested_c, int64_2), + MyGame::Example::NestedStruct(nested_a, MyGame::Example::TestEnum::B, + nested_c, + std::array{ { -2, -1 } }) } + }; + + auto different = MyGame::Example::NestedStruct( + nested_a, MyGame::Example::TestEnum::B, nested_cc, + std::array{ { -2, -1 } }); + + TEST_ASSERT(init_d[0] == init_d[1]); + TEST_ASSERT(init_d[0] != different); + + std::array arr_struct = { + MyGame::Example::ArrayStruct( + 8.125, + std::array{ + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }, + -17, init_d, 10, int64_2), + + MyGame::Example::ArrayStruct( + 8.125, + std::array{ + { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }, + -17, init_d, 10, int64_2), + + MyGame::Example::ArrayStruct( + 8.125, + std::array{ + { 1000, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } }, + -17, init_d, 10, int64_2) + }; + + TEST_ASSERT(arr_struct[0] == arr_struct[1]); + TEST_ASSERT(arr_struct[1] != arr_struct[2]); +} + void NativeTypeTest() { const int N = 3; @@ -1560,6 +1608,7 @@ int FlatBufferTests(const std::string &tests_data_path) { ParseFlexbuffersFromJsonWithNullTest(); FlatbuffersSpanTest(); FixedLengthArrayConstructorTest(); + FixedLengthArrayOpratorEqualTest(); FieldIdentifierTest(); StringVectorDefaultsTest(); FlexBuffersFloatingPointTest(); From 8a231235620fc31611008afd757f1d27849bfadf Mon Sep 17 00:00:00 2001 From: enum-class Date: Wed, 4 Jan 2023 22:09:10 +0800 Subject: [PATCH 2/4] Compare address --- include/flatbuffers/array.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/flatbuffers/array.h b/include/flatbuffers/array.h index 2227d08d2fb..3d035326690 100644 --- a/include/flatbuffers/array.h +++ b/include/flatbuffers/array.h @@ -17,6 +17,8 @@ #ifndef FLATBUFFERS_ARRAY_H_ #define FLATBUFFERS_ARRAY_H_ +#include + #include "flatbuffers/base.h" #include "flatbuffers/stl_emulation.h" #include "flatbuffers/vector.h" @@ -240,7 +242,8 @@ const Array &CastToArrayOfEnum(const T (&arr)[length]) { template bool operator==(const Array &lhs, const Array &rhs) { - return (lhs.size() == rhs.size() && + return std::addressof(lhs) == std::addressof(rhs) || + (lhs.size() == rhs.size() && std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0); } From 677ea584bc8343a3b54f74552afe37dfb3d630d4 Mon Sep 17 00:00:00 2001 From: enum-class Date: Wed, 4 Jan 2023 22:12:59 +0800 Subject: [PATCH 3/4] noexcept --- include/flatbuffers/array.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/flatbuffers/array.h b/include/flatbuffers/array.h index 3d035326690..2ff58c6fb59 100644 --- a/include/flatbuffers/array.h +++ b/include/flatbuffers/array.h @@ -241,7 +241,8 @@ const Array &CastToArrayOfEnum(const T (&arr)[length]) { } template -bool operator==(const Array &lhs, const Array &rhs) { +bool operator==(const Array &lhs, + const Array &rhs) noexcept { return std::addressof(lhs) == std::addressof(rhs) || (lhs.size() == rhs.size() && std::memcmp(lhs.Data(), rhs.Data(), rhs.size() * sizeof(T)) == 0); From c81ec55f15445e73d56dcb5c054967e4f8e5a1b6 Mon Sep 17 00:00:00 2001 From: enum-class Date: Wed, 4 Jan 2023 22:16:47 +0800 Subject: [PATCH 4/4] Grammer --- tests/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test.cpp b/tests/test.cpp index 27f2c2bfc3a..0ad755a3293 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -829,7 +829,7 @@ void FixedLengthArrayConstructorTest() { void FixedLengthArrayConstructorTest() {} #endif -void FixedLengthArrayOpratorEqualTest() { +void FixedLengthArrayOperatorEqualTest() { const int32_t nested_a[2] = { 1, 2 }; MyGame::Example::TestEnum nested_c[2] = { MyGame::Example::TestEnum::A, MyGame::Example::TestEnum::B }; @@ -1608,7 +1608,7 @@ int FlatBufferTests(const std::string &tests_data_path) { ParseFlexbuffersFromJsonWithNullTest(); FlatbuffersSpanTest(); FixedLengthArrayConstructorTest(); - FixedLengthArrayOpratorEqualTest(); + FixedLengthArrayOperatorEqualTest(); FieldIdentifierTest(); StringVectorDefaultsTest(); FlexBuffersFloatingPointTest();