mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 04:04:19 +00:00
Fix CreateVectorOfNativeStructs for non-std vector types (cpp_vec_type + native_type)
When a field combines cpp_vec_type (e.g. eastl::vector) with native_type on a struct, the generated Pack method now uses the pointer+size overload of CreateVectorOfNativeStructs instead of the std::vector overload, which only accepts std::vector. Adds a dedicated test covering the combined attribute case. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -241,6 +241,8 @@ set(FlatBuffers_Tests_SRCS
|
||||
tests/native_type_test_impl.h
|
||||
tests/native_type_test_impl.cpp
|
||||
tests/cpp_vec_type_test_impl.h
|
||||
tests/cpp_vec_type_native_type_test_impl.h
|
||||
tests/cpp_vec_type_native_type_test_impl.cpp
|
||||
tests/alignment_test.h
|
||||
tests/alignment_test.cpp
|
||||
tests/64bit/offset64_test.h
|
||||
@@ -556,6 +558,7 @@ if(FLATBUFFERS_BUILD_TESTS)
|
||||
compile_schema_for_test(tests/native_inline_table_test.fbs "${FLATC_OPT_COMP}")
|
||||
compile_schema_for_test(tests/native_type_test.fbs "${FLATC_OPT_COMP}")
|
||||
compile_schema_for_test(tests/cpp_vec_type_test.fbs "${FLATC_OPT_COMP}")
|
||||
compile_schema_for_test(tests/cpp_vec_type_native_type_test.fbs "${FLATC_OPT_COMP}")
|
||||
compile_schema_for_test(tests/key_field/key_field_sample.fbs "${FLATC_OPT_COMP}")
|
||||
compile_schema_for_test(tests/64bit/test_64bit.fbs "${FLATC_OPT_COMP};--bfbs-gen-embed")
|
||||
compile_schema_for_test(tests/64bit/evolution/v1.fbs "${FLATC_OPT_COMP}")
|
||||
|
||||
@@ -3833,7 +3833,6 @@ class CppGenerator : public BaseGenerator {
|
||||
code += "_fbb.CreateVectorOfNativeStructs<";
|
||||
code += WrapInNameSpace(*vector_type.struct_def) + ", " +
|
||||
native_type->constant + ">";
|
||||
code += "(" + value;
|
||||
// Field-level native_type_pack_name takes priority over
|
||||
// struct-level
|
||||
auto field_pack_name =
|
||||
@@ -3842,6 +3841,14 @@ class CppGenerator : public BaseGenerator {
|
||||
field_pack_name
|
||||
? field_pack_name
|
||||
: struct_attrs.Lookup("native_type_pack_name");
|
||||
// Non-std vectors (e.g. eastl::vector) don't match the
|
||||
// std::vector overload, so use the pointer+size overload.
|
||||
const bool is_std_vec = NativeVector(&field) == "std::vector";
|
||||
if (is_std_vec) {
|
||||
code += "(" + value;
|
||||
} else {
|
||||
code += "(" + value + ".data(), " + value + ".size()";
|
||||
}
|
||||
if (pack_name) {
|
||||
code += ", ::flatbuffers::Pack" + pack_name->constant;
|
||||
}
|
||||
|
||||
15
tests/cpp_vec_type_native_type_test.fbs
Normal file
15
tests/cpp_vec_type_native_type_test.fbs
Normal file
@@ -0,0 +1,15 @@
|
||||
native_include "cpp_vec_type_native_type_test_impl.h";
|
||||
|
||||
namespace CppVecNativeTypeTest;
|
||||
|
||||
struct Vec3 (native_type: "CppVecNativeTypeTest::Native::Vec3") {
|
||||
x: float;
|
||||
y: float;
|
||||
z: float;
|
||||
}
|
||||
|
||||
table Container {
|
||||
points: [Vec3] (cpp_vec_type: "CppVecNativeTypeTest::CustomVec");
|
||||
}
|
||||
|
||||
root_type Container;
|
||||
15
tests/cpp_vec_type_native_type_test_impl.cpp
Normal file
15
tests/cpp_vec_type_native_type_test_impl.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "cpp_vec_type_native_type_test_impl.h"
|
||||
|
||||
#include "cpp_vec_type_native_type_test_generated.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
CppVecNativeTypeTest::Vec3 Pack(
|
||||
const CppVecNativeTypeTest::Native::Vec3& obj) {
|
||||
return CppVecNativeTypeTest::Vec3(obj.x, obj.y, obj.z);
|
||||
}
|
||||
|
||||
const CppVecNativeTypeTest::Native::Vec3 UnPack(
|
||||
const CppVecNativeTypeTest::Vec3& obj) {
|
||||
return CppVecNativeTypeTest::Native::Vec3(obj.x(), obj.y(), obj.z());
|
||||
}
|
||||
} // namespace flatbuffers
|
||||
34
tests/cpp_vec_type_native_type_test_impl.h
Normal file
34
tests/cpp_vec_type_native_type_test_impl.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef CPP_VEC_TYPE_NATIVE_TYPE_TEST_IMPL_H
|
||||
#define CPP_VEC_TYPE_NATIVE_TYPE_TEST_IMPL_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace CppVecNativeTypeTest {
|
||||
|
||||
namespace Native {
|
||||
struct Vec3 {
|
||||
float x, y, z;
|
||||
Vec3() : x(0), y(0), z(0) {}
|
||||
Vec3(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {}
|
||||
bool operator==(const Vec3& o) const {
|
||||
return x == o.x && y == o.y && z == o.z;
|
||||
}
|
||||
};
|
||||
} // namespace Native
|
||||
|
||||
template <typename T>
|
||||
struct CustomVec : public std::vector<T> {
|
||||
using std::vector<T>::vector;
|
||||
};
|
||||
|
||||
struct Vec3; // flatbuffers-generated struct
|
||||
|
||||
} // namespace CppVecNativeTypeTest
|
||||
|
||||
namespace flatbuffers {
|
||||
CppVecNativeTypeTest::Vec3 Pack(const CppVecNativeTypeTest::Native::Vec3& obj);
|
||||
const CppVecNativeTypeTest::Native::Vec3 UnPack(
|
||||
const CppVecNativeTypeTest::Vec3& obj);
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // CPP_VEC_TYPE_NATIVE_TYPE_TEST_IMPL_H
|
||||
@@ -65,6 +65,7 @@
|
||||
#include "monster_test_bfbs_generated.h" // Generated using --bfbs-comments --bfbs-builtins --cpp --bfbs-gen-embed
|
||||
#include "cpp_vec_type_test_generated.h"
|
||||
#include "native_type_test_generated.h"
|
||||
#include "cpp_vec_type_native_type_test_generated.h"
|
||||
#include "test_assert.h"
|
||||
#include "util_test.h"
|
||||
#include "vector_table_naked_ptr_test.h"
|
||||
@@ -1041,6 +1042,37 @@ void CppVecTypeTest() {
|
||||
TEST_ASSERT(*dst == *dst);
|
||||
}
|
||||
|
||||
void CppVecTypeNativeTypeTest() {
|
||||
// Verify that combining cpp_vec_type + native_type on a vector of structs
|
||||
// produces the correct container type in the NativeTable.
|
||||
static_assert(
|
||||
std::is_same<
|
||||
decltype(CppVecNativeTypeTest::ContainerT{}.points),
|
||||
CppVecNativeTypeTest::CustomVec<
|
||||
CppVecNativeTypeTest::Native::Vec3>>::value,
|
||||
"points should be CustomVec<Native::Vec3>");
|
||||
|
||||
const int N = 3;
|
||||
CppVecNativeTypeTest::ContainerT src;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
src.points.push_back(
|
||||
CppVecNativeTypeTest::Native::Vec3(1.0f * i, 2.0f * i, 3.0f * i));
|
||||
}
|
||||
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
fbb.Finish(CppVecNativeTypeTest::Container::Pack(fbb, &src));
|
||||
|
||||
auto dst =
|
||||
CppVecNativeTypeTest::UnPackContainer(fbb.GetBufferPointer());
|
||||
|
||||
TEST_EQ(dst->points.size(), static_cast<size_t>(N));
|
||||
for (int i = 0; i < N; ++i) {
|
||||
TEST_EQ(dst->points[i].x, 1.0f * i);
|
||||
TEST_EQ(dst->points[i].y, 2.0f * i);
|
||||
TEST_EQ(dst->points[i].z, 3.0f * i);
|
||||
}
|
||||
}
|
||||
|
||||
// Guard against -Wunused-function on platforms without file tests.
|
||||
#ifndef FLATBUFFERS_NO_FILE_TESTS
|
||||
// VS10 does not support typed enums, exclude from tests
|
||||
@@ -1877,6 +1909,7 @@ int FlatBufferTests(const std::string& tests_data_path) {
|
||||
FixedLengthArrayTest();
|
||||
NativeTypeTest();
|
||||
CppVecTypeTest();
|
||||
CppVecTypeNativeTypeTest();
|
||||
OptionalScalarsTest();
|
||||
ParseFlexbuffersFromJsonWithNullTest();
|
||||
FlatbuffersSpanTest();
|
||||
|
||||
Reference in New Issue
Block a user