mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-29 10:42:00 +00:00
[C++17] Add compile-time reflection for fields. (#6324)
* [C++17] Add compile-time reflection for fields.
Included in this commit is the following:
- The C++ generator has been modified so that,
when in C++17 mode, it will emit Table and
Struct field traits that can be used at com-
pile time as a form of static reflection. This
includes field types, field names, and a tuple
of field getter results.
- Diffs to the cpp17 generated files. No other
generated files are affected.
- A unit test that also serves as an example. It
demonstrates how to use the full power of this
reflection to implement a full recursive
JSON-like stringifier for Flatbuffers types,
but without needing any runtime access to the
*.fbs definition files; the computation is
done using only static reflection.
Tested on Linux with gcc 10.2.0.
Fixes #6285.
* Fix int-conversion warning on MSVC.
* Try to fix std::to_string ambiguity on MSVC.
* Fix clang-format diffs.
* Fix more clang-format diffs.
* Fix last clang-format diff.
* Enable C++17 build/test for VC 19 platform in CI.
* Forgot to add value to cmake command line variable.
* Various fixes/changes in response to @vglavnyy's feedback.
* Replace "fields pack" with index-based getters.
* Fix MSVC error.
* Fix clang-format diffs.
* getter_for method returns result instead of address-of-getter.
* Next round of reviewer suggestions.
* Use type instead of hardcoded struct name.
* Fix clang-format diff.
* Add test for FieldType since it is not used in the stringify test.
* Add fields_number field to Traits struct.
* Add --cpp-static-reflection flag and put those features behind it.
* Fix clang-format diffs.
* Remove <tuple> include.
This commit is contained in:
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
|||||||
- name: Add msbuild to PATH
|
- name: Add msbuild to PATH
|
||||||
uses: microsoft/setup-msbuild@v1.0.2
|
uses: microsoft/setup-msbuild@v1.0.2
|
||||||
- name: cmake
|
- name: cmake
|
||||||
run: cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release .
|
run: cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release -DFLATBUFFERS_BUILD_CPP17=ON .
|
||||||
- name: build
|
- name: build
|
||||||
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
|
run: msbuild.exe FlatBuffers.sln /p:Configuration=Release /p:Platform=x64
|
||||||
- name: test
|
- name: test
|
||||||
|
|||||||
@@ -588,6 +588,7 @@ struct IDLOptions {
|
|||||||
bool cs_gen_json_serializer;
|
bool cs_gen_json_serializer;
|
||||||
std::vector<std::string> cpp_includes;
|
std::vector<std::string> cpp_includes;
|
||||||
std::string cpp_std;
|
std::string cpp_std;
|
||||||
|
bool cpp_static_reflection;
|
||||||
std::string proto_namespace_suffix;
|
std::string proto_namespace_suffix;
|
||||||
std::string filename_suffix;
|
std::string filename_suffix;
|
||||||
std::string filename_extension;
|
std::string filename_extension;
|
||||||
@@ -673,6 +674,7 @@ struct IDLOptions {
|
|||||||
force_defaults(false),
|
force_defaults(false),
|
||||||
java_primitive_has_method(false),
|
java_primitive_has_method(false),
|
||||||
cs_gen_json_serializer(false),
|
cs_gen_json_serializer(false),
|
||||||
|
cpp_static_reflection(false),
|
||||||
filename_suffix("_generated"),
|
filename_suffix("_generated"),
|
||||||
filename_extension(),
|
filename_extension(),
|
||||||
no_warnings(false),
|
no_warnings(false),
|
||||||
|
|||||||
@@ -126,6 +126,9 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
|
|||||||
" * 'c++0x' - generate code compatible with old compilers;\n"
|
" * 'c++0x' - generate code compatible with old compilers;\n"
|
||||||
" * 'c++11' - use C++11 code generator (default);\n"
|
" * 'c++11' - use C++11 code generator (default);\n"
|
||||||
" * 'c++17' - use C++17 features in generated code (experimental).\n"
|
" * 'c++17' - use C++17 features in generated code (experimental).\n"
|
||||||
|
" --cpp-static-reflection When using C++17, generate extra code to provide compile-time\n"
|
||||||
|
" (static) reflection of Flatbuffers types. Requires --cpp-std\n"
|
||||||
|
" to be \"c++17\" or higher.\n"
|
||||||
" --object-prefix Customise class prefix for C++ object-based API.\n"
|
" --object-prefix Customise class prefix for C++ object-based API.\n"
|
||||||
" --object-suffix Customise class suffix for C++ object-based API.\n"
|
" --object-suffix Customise class suffix for C++ object-based API.\n"
|
||||||
" Default value is \"T\".\n"
|
" Default value is \"T\".\n"
|
||||||
@@ -360,6 +363,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
|
|||||||
opts.cpp_std = argv[argi];
|
opts.cpp_std = argv[argi];
|
||||||
} else if (arg.rfind("--cpp-std=", 0) == 0) {
|
} else if (arg.rfind("--cpp-std=", 0) == 0) {
|
||||||
opts.cpp_std = arg.substr(std::string("--cpp-std=").size());
|
opts.cpp_std = arg.substr(std::string("--cpp-std=").size());
|
||||||
|
} else if (arg == "--cpp-static-reflection") {
|
||||||
|
opts.cpp_static_reflection = true;
|
||||||
} else {
|
} else {
|
||||||
for (size_t i = 0; i < params_.num_generators; ++i) {
|
for (size_t i = 0; i < params_.num_generators; ++i) {
|
||||||
if (arg == params_.generators[i].generator_opt_long ||
|
if (arg == params_.generators[i].generator_opt_long ||
|
||||||
|
|||||||
@@ -2041,6 +2041,135 @@ class CppGenerator : public BaseGenerator {
|
|||||||
if (type.base_type == BASE_TYPE_UNION) { GenTableUnionAsGetters(field); }
|
if (type.base_type == BASE_TYPE_UNION) { GenTableUnionAsGetters(field); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GenTableFieldType(const FieldDef &field) {
|
||||||
|
const auto &type = field.value.type;
|
||||||
|
const auto offset_str = GenFieldOffsetName(field);
|
||||||
|
if (!field.IsScalarOptional()) {
|
||||||
|
std::string afterptr = " *" + NullableExtension();
|
||||||
|
code_.SetValue("FIELD_TYPE",
|
||||||
|
GenTypeGet(type, "", "const ", afterptr.c_str(), true));
|
||||||
|
code_ += " {{FIELD_TYPE}}\\";
|
||||||
|
} else {
|
||||||
|
code_.SetValue("FIELD_TYPE", GenOptionalDecl(type));
|
||||||
|
code_ += " {{FIELD_TYPE}}\\";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenStructFieldType(const FieldDef &field) {
|
||||||
|
const auto is_array = IsArray(field.value.type);
|
||||||
|
std::string field_type =
|
||||||
|
GenTypeGet(field.value.type, "", is_array ? "" : "const ",
|
||||||
|
is_array ? "" : " &", true);
|
||||||
|
code_.SetValue("FIELD_TYPE", field_type);
|
||||||
|
code_ += " {{FIELD_TYPE}}\\";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenFieldTypeHelper(const StructDef &struct_def) {
|
||||||
|
if (struct_def.fields.vec.empty()) { return; }
|
||||||
|
code_ += " template<size_t Index>";
|
||||||
|
code_ += " using FieldType = \\";
|
||||||
|
code_ += "decltype(std::declval<type>().get_field<Index>());";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenIndexBasedFieldGetter(const StructDef &struct_def) {
|
||||||
|
if (struct_def.fields.vec.empty()) { return; }
|
||||||
|
code_ += " template<size_t Index>";
|
||||||
|
code_ += " auto get_field() const {";
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
bool need_else = false;
|
||||||
|
// Generate one index-based getter for each field.
|
||||||
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
|
it != struct_def.fields.vec.end(); ++it) {
|
||||||
|
const auto &field = **it;
|
||||||
|
if (field.deprecated) {
|
||||||
|
// Deprecated fields won't be accessible.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
code_.SetValue("FIELD_NAME", Name(field));
|
||||||
|
code_.SetValue("FIELD_INDEX",
|
||||||
|
std::to_string(static_cast<long long>(index++)));
|
||||||
|
if (need_else) {
|
||||||
|
code_ += " else \\";
|
||||||
|
} else {
|
||||||
|
code_ += " \\";
|
||||||
|
}
|
||||||
|
need_else = true;
|
||||||
|
code_ += "if constexpr (Index == {{FIELD_INDEX}}) \\";
|
||||||
|
code_ += "return {{FIELD_NAME}}();";
|
||||||
|
}
|
||||||
|
code_ += " else static_assert(Index != Index, \"Invalid Field Index\");";
|
||||||
|
code_ += " }";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample for Vec3:
|
||||||
|
//
|
||||||
|
// static constexpr std::array<const char *, 3> field_names = {
|
||||||
|
// "x",
|
||||||
|
// "y",
|
||||||
|
// "z"
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
void GenFieldNames(const StructDef &struct_def) {
|
||||||
|
auto non_deprecated_field_count = std::count_if(
|
||||||
|
struct_def.fields.vec.begin(), struct_def.fields.vec.end(),
|
||||||
|
[](const FieldDef *field) { return !field->deprecated; });
|
||||||
|
code_ += " static constexpr std::array<\\";
|
||||||
|
code_.SetValue(
|
||||||
|
"FIELD_COUNT",
|
||||||
|
std::to_string(static_cast<long long>(non_deprecated_field_count)));
|
||||||
|
code_ += "const char *, {{FIELD_COUNT}}> field_names = {\\";
|
||||||
|
if (struct_def.fields.vec.empty()) {
|
||||||
|
code_ += "};";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
code_ += "";
|
||||||
|
// Generate the field_names elements.
|
||||||
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
|
it != struct_def.fields.vec.end(); ++it) {
|
||||||
|
const auto &field = **it;
|
||||||
|
if (field.deprecated) {
|
||||||
|
// Deprecated fields won't be accessible.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
code_.SetValue("FIELD_NAME", Name(field));
|
||||||
|
code_ += " \"{{FIELD_NAME}}\"\\";
|
||||||
|
if (it + 1 != struct_def.fields.vec.end()) { code_ += ","; }
|
||||||
|
}
|
||||||
|
code_ += "\n };";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenFieldsNumber(const StructDef &struct_def) {
|
||||||
|
auto non_deprecated_field_count = std::count_if(
|
||||||
|
struct_def.fields.vec.begin(), struct_def.fields.vec.end(),
|
||||||
|
[](const FieldDef *field) { return !field->deprecated; });
|
||||||
|
code_.SetValue(
|
||||||
|
"FIELD_COUNT",
|
||||||
|
std::to_string(static_cast<long long>(non_deprecated_field_count)));
|
||||||
|
code_ += " static constexpr size_t fields_number = {{FIELD_COUNT}};";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GenTraitsStruct(const StructDef &struct_def) {
|
||||||
|
code_.SetValue(
|
||||||
|
"FULLY_QUALIFIED_NAME",
|
||||||
|
struct_def.defined_namespace->GetFullyQualifiedName(Name(struct_def)));
|
||||||
|
code_ += "struct {{STRUCT_NAME}}::Traits {";
|
||||||
|
code_ += " using type = {{STRUCT_NAME}};";
|
||||||
|
if (!struct_def.fixed) {
|
||||||
|
// We have a table and not a struct.
|
||||||
|
code_ += " static auto constexpr Create = Create{{STRUCT_NAME}};";
|
||||||
|
}
|
||||||
|
code_ += " static constexpr auto name = \"{{STRUCT_NAME}}\";";
|
||||||
|
code_ +=
|
||||||
|
" static constexpr auto fully_qualified_name = "
|
||||||
|
"\"{{FULLY_QUALIFIED_NAME}}\";";
|
||||||
|
GenFieldNames(struct_def);
|
||||||
|
GenFieldTypeHelper(struct_def);
|
||||||
|
GenFieldsNumber(struct_def);
|
||||||
|
code_ += "};";
|
||||||
|
code_ += "";
|
||||||
|
}
|
||||||
|
|
||||||
void GenTableFieldSetter(const FieldDef &field) {
|
void GenTableFieldSetter(const FieldDef &field) {
|
||||||
const auto &type = field.value.type;
|
const auto &type = field.value.type;
|
||||||
const bool is_scalar = IsScalar(type.base_type);
|
const bool is_scalar = IsScalar(type.base_type);
|
||||||
@@ -2098,7 +2227,7 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code_ += " typedef {{NATIVE_NAME}} NativeTableType;";
|
code_ += " typedef {{NATIVE_NAME}} NativeTableType;";
|
||||||
}
|
}
|
||||||
code_ += " typedef {{STRUCT_NAME}}Builder Builder;";
|
code_ += " typedef {{STRUCT_NAME}}Builder Builder;";
|
||||||
if (opts_.g_cpp_std >= cpp::CPP_STD_17) { code_ += " struct Traits;"; }
|
if (opts_.cpp_static_reflection) { code_ += " struct Traits;"; }
|
||||||
if (opts_.mini_reflect != IDLOptions::kNone) {
|
if (opts_.mini_reflect != IDLOptions::kNone) {
|
||||||
code_ +=
|
code_ +=
|
||||||
" static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
|
" static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
|
||||||
@@ -2181,6 +2310,8 @@ class CppGenerator : public BaseGenerator {
|
|||||||
if (field.key) { GenKeyFieldMethods(field); }
|
if (field.key) { GenKeyFieldMethods(field); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opts_.cpp_static_reflection) { GenIndexBasedFieldGetter(struct_def); }
|
||||||
|
|
||||||
// Generate a verifier function that can check a buffer from an untrusted
|
// Generate a verifier function that can check a buffer from an untrusted
|
||||||
// source will never cause reads outside the buffer.
|
// source will never cause reads outside the buffer.
|
||||||
code_ += " bool Verify(flatbuffers::Verifier &verifier) const {";
|
code_ += " bool Verify(flatbuffers::Verifier &verifier) const {";
|
||||||
@@ -2388,13 +2519,7 @@ class CppGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
// Definition for type traits for this table type. This allows querying var-
|
// Definition for type traits for this table type. This allows querying var-
|
||||||
// ious compile-time traits of the table.
|
// ious compile-time traits of the table.
|
||||||
if (opts_.g_cpp_std >= cpp::CPP_STD_17) {
|
if (opts_.cpp_static_reflection) { GenTraitsStruct(struct_def); }
|
||||||
code_ += "struct {{STRUCT_NAME}}::Traits {";
|
|
||||||
code_ += " using type = {{STRUCT_NAME}};";
|
|
||||||
code_ += " static auto constexpr Create = Create{{STRUCT_NAME}};";
|
|
||||||
code_ += "};";
|
|
||||||
code_ += "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate a CreateXDirect function with vector types as parameters
|
// Generate a CreateXDirect function with vector types as parameters
|
||||||
if (opts_.cpp_direct_copy && has_string_or_vector_fields) {
|
if (opts_.cpp_direct_copy && has_string_or_vector_fields) {
|
||||||
@@ -3168,6 +3293,8 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code_ += "";
|
code_ += "";
|
||||||
code_ += " public:";
|
code_ += " public:";
|
||||||
|
|
||||||
|
if (opts_.cpp_static_reflection) { code_ += " struct Traits;"; }
|
||||||
|
|
||||||
// Make TypeTable accessible via the generated struct.
|
// Make TypeTable accessible via the generated struct.
|
||||||
if (opts_.mini_reflect != IDLOptions::kNone) {
|
if (opts_.mini_reflect != IDLOptions::kNone) {
|
||||||
code_ +=
|
code_ +=
|
||||||
@@ -3253,12 +3380,19 @@ class CppGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
code_.SetValue("NATIVE_NAME", Name(struct_def));
|
code_.SetValue("NATIVE_NAME", Name(struct_def));
|
||||||
GenOperatorNewDelete(struct_def);
|
GenOperatorNewDelete(struct_def);
|
||||||
|
|
||||||
|
if (opts_.cpp_static_reflection) { GenIndexBasedFieldGetter(struct_def); }
|
||||||
|
|
||||||
code_ += "};";
|
code_ += "};";
|
||||||
|
|
||||||
code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize));
|
code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize));
|
||||||
code_ += "FLATBUFFERS_STRUCT_END({{STRUCT_NAME}}, {{STRUCT_BYTE_SIZE}});";
|
code_ += "FLATBUFFERS_STRUCT_END({{STRUCT_NAME}}, {{STRUCT_BYTE_SIZE}});";
|
||||||
if (opts_.gen_compare) GenCompareOperator(struct_def, "()");
|
if (opts_.gen_compare) GenCompareOperator(struct_def, "()");
|
||||||
code_ += "";
|
code_ += "";
|
||||||
|
|
||||||
|
// Definition for type traits for this table type. This allows querying var-
|
||||||
|
// ious compile-time traits of the table.
|
||||||
|
if (opts_.cpp_static_reflection) { GenTraitsStruct(struct_def); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the correct namespace. Only open a namespace if the existing one is
|
// Set up the correct namespace. Only open a namespace if the existing one is
|
||||||
@@ -3331,6 +3465,13 @@ bool GenerateCPP(const Parser &parser, const std::string &path,
|
|||||||
// The opts.scoped_enums has priority.
|
// The opts.scoped_enums has priority.
|
||||||
opts.g_only_fixed_enums |= opts.scoped_enums;
|
opts.g_only_fixed_enums |= opts.scoped_enums;
|
||||||
|
|
||||||
|
if (opts.cpp_static_reflection && opts.g_cpp_std < cpp::CPP_STD_17) {
|
||||||
|
LogCompilerError(
|
||||||
|
"--cpp-static-reflection requires using --cpp-std at \"C++17\" or "
|
||||||
|
"higher.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
cpp::CppGenerator generator(parser, path, file_name, opts);
|
cpp::CppGenerator generator(parser, path, file_name, opts);
|
||||||
return generator.generate();
|
return generator.generate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -474,6 +474,7 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS {
|
|||||||
int8_t padding0__;
|
int8_t padding0__;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return TestTypeTable();
|
return TestTypeTable();
|
||||||
}
|
}
|
||||||
@@ -501,9 +502,28 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS {
|
|||||||
void mutate_b(int8_t _b) {
|
void mutate_b(int8_t _b) {
|
||||||
flatbuffers::WriteScalar(&b_, _b);
|
flatbuffers::WriteScalar(&b_, _b);
|
||||||
}
|
}
|
||||||
|
template<size_t Index>
|
||||||
|
auto get_field() const {
|
||||||
|
if constexpr (Index == 0) return a();
|
||||||
|
else if constexpr (Index == 1) return b();
|
||||||
|
else static_assert(Index != Index, "Invalid Field Index");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
FLATBUFFERS_STRUCT_END(Test, 4);
|
FLATBUFFERS_STRUCT_END(Test, 4);
|
||||||
|
|
||||||
|
struct Test::Traits {
|
||||||
|
using type = Test;
|
||||||
|
static constexpr auto name = "Test";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.Example.Test";
|
||||||
|
static constexpr std::array<const char *, 2> field_names = {
|
||||||
|
"a",
|
||||||
|
"b"
|
||||||
|
};
|
||||||
|
template<size_t Index>
|
||||||
|
using FieldType = decltype(std::declval<type>().get_field<Index>());
|
||||||
|
static constexpr size_t fields_number = 2;
|
||||||
|
};
|
||||||
|
|
||||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Vec3 FLATBUFFERS_FINAL_CLASS {
|
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Vec3 FLATBUFFERS_FINAL_CLASS {
|
||||||
private:
|
private:
|
||||||
float x_;
|
float x_;
|
||||||
@@ -517,6 +537,7 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Vec3 FLATBUFFERS_FINAL_CLASS {
|
|||||||
int16_t padding2__;
|
int16_t padding2__;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return Vec3TypeTable();
|
return Vec3TypeTable();
|
||||||
}
|
}
|
||||||
@@ -584,15 +605,43 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Vec3 FLATBUFFERS_FINAL_CLASS {
|
|||||||
MyGame::Example::Test &mutable_test3() {
|
MyGame::Example::Test &mutable_test3() {
|
||||||
return test3_;
|
return test3_;
|
||||||
}
|
}
|
||||||
|
template<size_t Index>
|
||||||
|
auto get_field() const {
|
||||||
|
if constexpr (Index == 0) return x();
|
||||||
|
else if constexpr (Index == 1) return y();
|
||||||
|
else if constexpr (Index == 2) return z();
|
||||||
|
else if constexpr (Index == 3) return test1();
|
||||||
|
else if constexpr (Index == 4) return test2();
|
||||||
|
else if constexpr (Index == 5) return test3();
|
||||||
|
else static_assert(Index != Index, "Invalid Field Index");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
FLATBUFFERS_STRUCT_END(Vec3, 32);
|
FLATBUFFERS_STRUCT_END(Vec3, 32);
|
||||||
|
|
||||||
|
struct Vec3::Traits {
|
||||||
|
using type = Vec3;
|
||||||
|
static constexpr auto name = "Vec3";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.Example.Vec3";
|
||||||
|
static constexpr std::array<const char *, 6> field_names = {
|
||||||
|
"x",
|
||||||
|
"y",
|
||||||
|
"z",
|
||||||
|
"test1",
|
||||||
|
"test2",
|
||||||
|
"test3"
|
||||||
|
};
|
||||||
|
template<size_t Index>
|
||||||
|
using FieldType = decltype(std::declval<type>().get_field<Index>());
|
||||||
|
static constexpr size_t fields_number = 6;
|
||||||
|
};
|
||||||
|
|
||||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS {
|
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS {
|
||||||
private:
|
private:
|
||||||
uint32_t id_;
|
uint32_t id_;
|
||||||
uint32_t distance_;
|
uint32_t distance_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return AbilityTypeTable();
|
return AbilityTypeTable();
|
||||||
}
|
}
|
||||||
@@ -622,9 +671,28 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS {
|
|||||||
void mutate_distance(uint32_t _distance) {
|
void mutate_distance(uint32_t _distance) {
|
||||||
flatbuffers::WriteScalar(&distance_, _distance);
|
flatbuffers::WriteScalar(&distance_, _distance);
|
||||||
}
|
}
|
||||||
|
template<size_t Index>
|
||||||
|
auto get_field() const {
|
||||||
|
if constexpr (Index == 0) return id();
|
||||||
|
else if constexpr (Index == 1) return distance();
|
||||||
|
else static_assert(Index != Index, "Invalid Field Index");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
FLATBUFFERS_STRUCT_END(Ability, 8);
|
FLATBUFFERS_STRUCT_END(Ability, 8);
|
||||||
|
|
||||||
|
struct Ability::Traits {
|
||||||
|
using type = Ability;
|
||||||
|
static constexpr auto name = "Ability";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.Example.Ability";
|
||||||
|
static constexpr std::array<const char *, 2> field_names = {
|
||||||
|
"id",
|
||||||
|
"distance"
|
||||||
|
};
|
||||||
|
template<size_t Index>
|
||||||
|
using FieldType = decltype(std::declval<type>().get_field<Index>());
|
||||||
|
static constexpr size_t fields_number = 2;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace Example
|
} // namespace Example
|
||||||
|
|
||||||
struct InParentNamespaceT : public flatbuffers::NativeTable {
|
struct InParentNamespaceT : public flatbuffers::NativeTable {
|
||||||
@@ -671,6 +739,10 @@ inline flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(
|
|||||||
struct InParentNamespace::Traits {
|
struct InParentNamespace::Traits {
|
||||||
using type = InParentNamespace;
|
using type = InParentNamespace;
|
||||||
static auto constexpr Create = CreateInParentNamespace;
|
static auto constexpr Create = CreateInParentNamespace;
|
||||||
|
static constexpr auto name = "InParentNamespace";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.InParentNamespace";
|
||||||
|
static constexpr std::array<const char *, 0> field_names = {};
|
||||||
|
static constexpr size_t fields_number = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(flatbuffers::FlatBufferBuilder &_fbb, const InParentNamespaceT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(flatbuffers::FlatBufferBuilder &_fbb, const InParentNamespaceT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
@@ -721,6 +793,10 @@ inline flatbuffers::Offset<Monster> CreateMonster(
|
|||||||
struct Monster::Traits {
|
struct Monster::Traits {
|
||||||
using type = Monster;
|
using type = Monster;
|
||||||
static auto constexpr Create = CreateMonster;
|
static auto constexpr Create = CreateMonster;
|
||||||
|
static constexpr auto name = "Monster";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.Example2.Monster";
|
||||||
|
static constexpr std::array<const char *, 0> field_names = {};
|
||||||
|
static constexpr size_t fields_number = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
@@ -750,6 +826,11 @@ struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta
|
|||||||
bool mutate_color(MyGame::Example::Color _color) {
|
bool mutate_color(MyGame::Example::Color _color) {
|
||||||
return SetField<uint8_t>(VT_COLOR, static_cast<uint8_t>(_color), 2);
|
return SetField<uint8_t>(VT_COLOR, static_cast<uint8_t>(_color), 2);
|
||||||
}
|
}
|
||||||
|
template<size_t Index>
|
||||||
|
auto get_field() const {
|
||||||
|
if constexpr (Index == 0) return color();
|
||||||
|
else static_assert(Index != Index, "Invalid Field Index");
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyField<uint8_t>(verifier, VT_COLOR) &&
|
VerifyField<uint8_t>(verifier, VT_COLOR) &&
|
||||||
@@ -789,6 +870,14 @@ inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnu
|
|||||||
struct TestSimpleTableWithEnum::Traits {
|
struct TestSimpleTableWithEnum::Traits {
|
||||||
using type = TestSimpleTableWithEnum;
|
using type = TestSimpleTableWithEnum;
|
||||||
static auto constexpr Create = CreateTestSimpleTableWithEnum;
|
static auto constexpr Create = CreateTestSimpleTableWithEnum;
|
||||||
|
static constexpr auto name = "TestSimpleTableWithEnum";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.Example.TestSimpleTableWithEnum";
|
||||||
|
static constexpr std::array<const char *, 1> field_names = {
|
||||||
|
"color"
|
||||||
|
};
|
||||||
|
template<size_t Index>
|
||||||
|
using FieldType = decltype(std::declval<type>().get_field<Index>());
|
||||||
|
static constexpr size_t fields_number = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
@@ -836,6 +925,13 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
int KeyCompareWithValue(uint16_t val) const {
|
int KeyCompareWithValue(uint16_t val) const {
|
||||||
return static_cast<int>(count() > val) - static_cast<int>(count() < val);
|
return static_cast<int>(count() > val) - static_cast<int>(count() < val);
|
||||||
}
|
}
|
||||||
|
template<size_t Index>
|
||||||
|
auto get_field() const {
|
||||||
|
if constexpr (Index == 0) return id();
|
||||||
|
else if constexpr (Index == 1) return val();
|
||||||
|
else if constexpr (Index == 2) return count();
|
||||||
|
else static_assert(Index != Index, "Invalid Field Index");
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyOffset(verifier, VT_ID) &&
|
VerifyOffset(verifier, VT_ID) &&
|
||||||
@@ -888,6 +984,16 @@ inline flatbuffers::Offset<Stat> CreateStat(
|
|||||||
struct Stat::Traits {
|
struct Stat::Traits {
|
||||||
using type = Stat;
|
using type = Stat;
|
||||||
static auto constexpr Create = CreateStat;
|
static auto constexpr Create = CreateStat;
|
||||||
|
static constexpr auto name = "Stat";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.Example.Stat";
|
||||||
|
static constexpr std::array<const char *, 3> field_names = {
|
||||||
|
"id",
|
||||||
|
"val",
|
||||||
|
"count"
|
||||||
|
};
|
||||||
|
template<size_t Index>
|
||||||
|
using FieldType = decltype(std::declval<type>().get_field<Index>());
|
||||||
|
static constexpr size_t fields_number = 3;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline flatbuffers::Offset<Stat> CreateStatDirect(
|
inline flatbuffers::Offset<Stat> CreateStatDirect(
|
||||||
@@ -932,6 +1038,11 @@ struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
int KeyCompareWithValue(uint64_t val) const {
|
int KeyCompareWithValue(uint64_t val) const {
|
||||||
return static_cast<int>(id() > val) - static_cast<int>(id() < val);
|
return static_cast<int>(id() > val) - static_cast<int>(id() < val);
|
||||||
}
|
}
|
||||||
|
template<size_t Index>
|
||||||
|
auto get_field() const {
|
||||||
|
if constexpr (Index == 0) return id();
|
||||||
|
else static_assert(Index != Index, "Invalid Field Index");
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyField<uint64_t>(verifier, VT_ID) &&
|
VerifyField<uint64_t>(verifier, VT_ID) &&
|
||||||
@@ -971,6 +1082,14 @@ inline flatbuffers::Offset<Referrable> CreateReferrable(
|
|||||||
struct Referrable::Traits {
|
struct Referrable::Traits {
|
||||||
using type = Referrable;
|
using type = Referrable;
|
||||||
static auto constexpr Create = CreateReferrable;
|
static auto constexpr Create = CreateReferrable;
|
||||||
|
static constexpr auto name = "Referrable";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.Example.Referrable";
|
||||||
|
static constexpr std::array<const char *, 1> field_names = {
|
||||||
|
"id"
|
||||||
|
};
|
||||||
|
template<size_t Index>
|
||||||
|
using FieldType = decltype(std::declval<type>().get_field<Index>());
|
||||||
|
static constexpr size_t fields_number = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
flatbuffers::Offset<Referrable> CreateReferrable(flatbuffers::FlatBufferBuilder &_fbb, const ReferrableT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
flatbuffers::Offset<Referrable> CreateReferrable(flatbuffers::FlatBufferBuilder &_fbb, const ReferrableT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
@@ -1423,6 +1542,60 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
flatbuffers::Vector<flatbuffers::Offset<MyGame::Example::Stat>> *mutable_scalar_key_sorted_tables() {
|
flatbuffers::Vector<flatbuffers::Offset<MyGame::Example::Stat>> *mutable_scalar_key_sorted_tables() {
|
||||||
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<MyGame::Example::Stat>> *>(VT_SCALAR_KEY_SORTED_TABLES);
|
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<MyGame::Example::Stat>> *>(VT_SCALAR_KEY_SORTED_TABLES);
|
||||||
}
|
}
|
||||||
|
template<size_t Index>
|
||||||
|
auto get_field() const {
|
||||||
|
if constexpr (Index == 0) return pos();
|
||||||
|
else if constexpr (Index == 1) return mana();
|
||||||
|
else if constexpr (Index == 2) return hp();
|
||||||
|
else if constexpr (Index == 3) return name();
|
||||||
|
else if constexpr (Index == 4) return inventory();
|
||||||
|
else if constexpr (Index == 5) return color();
|
||||||
|
else if constexpr (Index == 6) return test_type();
|
||||||
|
else if constexpr (Index == 7) return test();
|
||||||
|
else if constexpr (Index == 8) return test4();
|
||||||
|
else if constexpr (Index == 9) return testarrayofstring();
|
||||||
|
else if constexpr (Index == 10) return testarrayoftables();
|
||||||
|
else if constexpr (Index == 11) return enemy();
|
||||||
|
else if constexpr (Index == 12) return testnestedflatbuffer();
|
||||||
|
else if constexpr (Index == 13) return testempty();
|
||||||
|
else if constexpr (Index == 14) return testbool();
|
||||||
|
else if constexpr (Index == 15) return testhashs32_fnv1();
|
||||||
|
else if constexpr (Index == 16) return testhashu32_fnv1();
|
||||||
|
else if constexpr (Index == 17) return testhashs64_fnv1();
|
||||||
|
else if constexpr (Index == 18) return testhashu64_fnv1();
|
||||||
|
else if constexpr (Index == 19) return testhashs32_fnv1a();
|
||||||
|
else if constexpr (Index == 20) return testhashu32_fnv1a();
|
||||||
|
else if constexpr (Index == 21) return testhashs64_fnv1a();
|
||||||
|
else if constexpr (Index == 22) return testhashu64_fnv1a();
|
||||||
|
else if constexpr (Index == 23) return testarrayofbools();
|
||||||
|
else if constexpr (Index == 24) return testf();
|
||||||
|
else if constexpr (Index == 25) return testf2();
|
||||||
|
else if constexpr (Index == 26) return testf3();
|
||||||
|
else if constexpr (Index == 27) return testarrayofstring2();
|
||||||
|
else if constexpr (Index == 28) return testarrayofsortedstruct();
|
||||||
|
else if constexpr (Index == 29) return flex();
|
||||||
|
else if constexpr (Index == 30) return test5();
|
||||||
|
else if constexpr (Index == 31) return vector_of_longs();
|
||||||
|
else if constexpr (Index == 32) return vector_of_doubles();
|
||||||
|
else if constexpr (Index == 33) return parent_namespace_test();
|
||||||
|
else if constexpr (Index == 34) return vector_of_referrables();
|
||||||
|
else if constexpr (Index == 35) return single_weak_reference();
|
||||||
|
else if constexpr (Index == 36) return vector_of_weak_references();
|
||||||
|
else if constexpr (Index == 37) return vector_of_strong_referrables();
|
||||||
|
else if constexpr (Index == 38) return co_owning_reference();
|
||||||
|
else if constexpr (Index == 39) return vector_of_co_owning_references();
|
||||||
|
else if constexpr (Index == 40) return non_owning_reference();
|
||||||
|
else if constexpr (Index == 41) return vector_of_non_owning_references();
|
||||||
|
else if constexpr (Index == 42) return any_unique_type();
|
||||||
|
else if constexpr (Index == 43) return any_unique();
|
||||||
|
else if constexpr (Index == 44) return any_ambiguous_type();
|
||||||
|
else if constexpr (Index == 45) return any_ambiguous();
|
||||||
|
else if constexpr (Index == 46) return vector_of_enums();
|
||||||
|
else if constexpr (Index == 47) return signed_enum();
|
||||||
|
else if constexpr (Index == 48) return testrequirednestedflatbuffer();
|
||||||
|
else if constexpr (Index == 49) return scalar_key_sorted_tables();
|
||||||
|
else static_assert(Index != Index, "Invalid Field Index");
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyField<MyGame::Example::Vec3>(verifier, VT_POS) &&
|
VerifyField<MyGame::Example::Vec3>(verifier, VT_POS) &&
|
||||||
@@ -1814,6 +1987,63 @@ inline flatbuffers::Offset<Monster> CreateMonster(
|
|||||||
struct Monster::Traits {
|
struct Monster::Traits {
|
||||||
using type = Monster;
|
using type = Monster;
|
||||||
static auto constexpr Create = CreateMonster;
|
static auto constexpr Create = CreateMonster;
|
||||||
|
static constexpr auto name = "Monster";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.Example.Monster";
|
||||||
|
static constexpr std::array<const char *, 50> field_names = {
|
||||||
|
"pos",
|
||||||
|
"mana",
|
||||||
|
"hp",
|
||||||
|
"name",
|
||||||
|
"inventory",
|
||||||
|
"color",
|
||||||
|
"test_type",
|
||||||
|
"test",
|
||||||
|
"test4",
|
||||||
|
"testarrayofstring",
|
||||||
|
"testarrayoftables",
|
||||||
|
"enemy",
|
||||||
|
"testnestedflatbuffer",
|
||||||
|
"testempty",
|
||||||
|
"testbool",
|
||||||
|
"testhashs32_fnv1",
|
||||||
|
"testhashu32_fnv1",
|
||||||
|
"testhashs64_fnv1",
|
||||||
|
"testhashu64_fnv1",
|
||||||
|
"testhashs32_fnv1a",
|
||||||
|
"testhashu32_fnv1a",
|
||||||
|
"testhashs64_fnv1a",
|
||||||
|
"testhashu64_fnv1a",
|
||||||
|
"testarrayofbools",
|
||||||
|
"testf",
|
||||||
|
"testf2",
|
||||||
|
"testf3",
|
||||||
|
"testarrayofstring2",
|
||||||
|
"testarrayofsortedstruct",
|
||||||
|
"flex",
|
||||||
|
"test5",
|
||||||
|
"vector_of_longs",
|
||||||
|
"vector_of_doubles",
|
||||||
|
"parent_namespace_test",
|
||||||
|
"vector_of_referrables",
|
||||||
|
"single_weak_reference",
|
||||||
|
"vector_of_weak_references",
|
||||||
|
"vector_of_strong_referrables",
|
||||||
|
"co_owning_reference",
|
||||||
|
"vector_of_co_owning_references",
|
||||||
|
"non_owning_reference",
|
||||||
|
"vector_of_non_owning_references",
|
||||||
|
"any_unique_type",
|
||||||
|
"any_unique",
|
||||||
|
"any_ambiguous_type",
|
||||||
|
"any_ambiguous",
|
||||||
|
"vector_of_enums",
|
||||||
|
"signed_enum",
|
||||||
|
"testrequirednestedflatbuffer",
|
||||||
|
"scalar_key_sorted_tables"
|
||||||
|
};
|
||||||
|
template<size_t Index>
|
||||||
|
using FieldType = decltype(std::declval<type>().get_field<Index>());
|
||||||
|
static constexpr size_t fields_number = 50;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline flatbuffers::Offset<Monster> CreateMonsterDirect(
|
inline flatbuffers::Offset<Monster> CreateMonsterDirect(
|
||||||
@@ -2054,6 +2284,22 @@ struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
flatbuffers::Vector<double> *mutable_vf64() {
|
flatbuffers::Vector<double> *mutable_vf64() {
|
||||||
return GetPointer<flatbuffers::Vector<double> *>(VT_VF64);
|
return GetPointer<flatbuffers::Vector<double> *>(VT_VF64);
|
||||||
}
|
}
|
||||||
|
template<size_t Index>
|
||||||
|
auto get_field() const {
|
||||||
|
if constexpr (Index == 0) return i8();
|
||||||
|
else if constexpr (Index == 1) return u8();
|
||||||
|
else if constexpr (Index == 2) return i16();
|
||||||
|
else if constexpr (Index == 3) return u16();
|
||||||
|
else if constexpr (Index == 4) return i32();
|
||||||
|
else if constexpr (Index == 5) return u32();
|
||||||
|
else if constexpr (Index == 6) return i64();
|
||||||
|
else if constexpr (Index == 7) return u64();
|
||||||
|
else if constexpr (Index == 8) return f32();
|
||||||
|
else if constexpr (Index == 9) return f64();
|
||||||
|
else if constexpr (Index == 10) return v8();
|
||||||
|
else if constexpr (Index == 11) return vf64();
|
||||||
|
else static_assert(Index != Index, "Invalid Field Index");
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyField<int8_t>(verifier, VT_I8) &&
|
VerifyField<int8_t>(verifier, VT_I8) &&
|
||||||
@@ -2161,6 +2407,25 @@ inline flatbuffers::Offset<TypeAliases> CreateTypeAliases(
|
|||||||
struct TypeAliases::Traits {
|
struct TypeAliases::Traits {
|
||||||
using type = TypeAliases;
|
using type = TypeAliases;
|
||||||
static auto constexpr Create = CreateTypeAliases;
|
static auto constexpr Create = CreateTypeAliases;
|
||||||
|
static constexpr auto name = "TypeAliases";
|
||||||
|
static constexpr auto fully_qualified_name = "MyGame.Example.TypeAliases";
|
||||||
|
static constexpr std::array<const char *, 12> field_names = {
|
||||||
|
"i8",
|
||||||
|
"u8",
|
||||||
|
"i16",
|
||||||
|
"u16",
|
||||||
|
"i32",
|
||||||
|
"u32",
|
||||||
|
"i64",
|
||||||
|
"u64",
|
||||||
|
"f32",
|
||||||
|
"f64",
|
||||||
|
"v8",
|
||||||
|
"vf64"
|
||||||
|
};
|
||||||
|
template<size_t Index>
|
||||||
|
using FieldType = decltype(std::declval<type>().get_field<Index>());
|
||||||
|
static constexpr size_t fields_number = 12;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline flatbuffers::Offset<TypeAliases> CreateTypeAliasesDirect(
|
inline flatbuffers::Offset<TypeAliases> CreateTypeAliasesDirect(
|
||||||
|
|||||||
@@ -348,6 +348,46 @@ struct ScalarStuff FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
bool mutate_default_enum(optional_scalars::OptionalByte _default_enum) {
|
bool mutate_default_enum(optional_scalars::OptionalByte _default_enum) {
|
||||||
return SetField<int8_t>(VT_DEFAULT_ENUM, static_cast<int8_t>(_default_enum), 1);
|
return SetField<int8_t>(VT_DEFAULT_ENUM, static_cast<int8_t>(_default_enum), 1);
|
||||||
}
|
}
|
||||||
|
template<size_t Index>
|
||||||
|
auto get_field() const {
|
||||||
|
if constexpr (Index == 0) return just_i8();
|
||||||
|
else if constexpr (Index == 1) return maybe_i8();
|
||||||
|
else if constexpr (Index == 2) return default_i8();
|
||||||
|
else if constexpr (Index == 3) return just_u8();
|
||||||
|
else if constexpr (Index == 4) return maybe_u8();
|
||||||
|
else if constexpr (Index == 5) return default_u8();
|
||||||
|
else if constexpr (Index == 6) return just_i16();
|
||||||
|
else if constexpr (Index == 7) return maybe_i16();
|
||||||
|
else if constexpr (Index == 8) return default_i16();
|
||||||
|
else if constexpr (Index == 9) return just_u16();
|
||||||
|
else if constexpr (Index == 10) return maybe_u16();
|
||||||
|
else if constexpr (Index == 11) return default_u16();
|
||||||
|
else if constexpr (Index == 12) return just_i32();
|
||||||
|
else if constexpr (Index == 13) return maybe_i32();
|
||||||
|
else if constexpr (Index == 14) return default_i32();
|
||||||
|
else if constexpr (Index == 15) return just_u32();
|
||||||
|
else if constexpr (Index == 16) return maybe_u32();
|
||||||
|
else if constexpr (Index == 17) return default_u32();
|
||||||
|
else if constexpr (Index == 18) return just_i64();
|
||||||
|
else if constexpr (Index == 19) return maybe_i64();
|
||||||
|
else if constexpr (Index == 20) return default_i64();
|
||||||
|
else if constexpr (Index == 21) return just_u64();
|
||||||
|
else if constexpr (Index == 22) return maybe_u64();
|
||||||
|
else if constexpr (Index == 23) return default_u64();
|
||||||
|
else if constexpr (Index == 24) return just_f32();
|
||||||
|
else if constexpr (Index == 25) return maybe_f32();
|
||||||
|
else if constexpr (Index == 26) return default_f32();
|
||||||
|
else if constexpr (Index == 27) return just_f64();
|
||||||
|
else if constexpr (Index == 28) return maybe_f64();
|
||||||
|
else if constexpr (Index == 29) return default_f64();
|
||||||
|
else if constexpr (Index == 30) return just_bool();
|
||||||
|
else if constexpr (Index == 31) return maybe_bool();
|
||||||
|
else if constexpr (Index == 32) return default_bool();
|
||||||
|
else if constexpr (Index == 33) return just_enum();
|
||||||
|
else if constexpr (Index == 34) return maybe_enum();
|
||||||
|
else if constexpr (Index == 35) return default_enum();
|
||||||
|
else static_assert(Index != Index, "Invalid Field Index");
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyField<int8_t>(verifier, VT_JUST_I8) &&
|
VerifyField<int8_t>(verifier, VT_JUST_I8) &&
|
||||||
@@ -597,6 +637,49 @@ inline flatbuffers::Offset<ScalarStuff> CreateScalarStuff(
|
|||||||
struct ScalarStuff::Traits {
|
struct ScalarStuff::Traits {
|
||||||
using type = ScalarStuff;
|
using type = ScalarStuff;
|
||||||
static auto constexpr Create = CreateScalarStuff;
|
static auto constexpr Create = CreateScalarStuff;
|
||||||
|
static constexpr auto name = "ScalarStuff";
|
||||||
|
static constexpr auto fully_qualified_name = "optional_scalars.ScalarStuff";
|
||||||
|
static constexpr std::array<const char *, 36> field_names = {
|
||||||
|
"just_i8",
|
||||||
|
"maybe_i8",
|
||||||
|
"default_i8",
|
||||||
|
"just_u8",
|
||||||
|
"maybe_u8",
|
||||||
|
"default_u8",
|
||||||
|
"just_i16",
|
||||||
|
"maybe_i16",
|
||||||
|
"default_i16",
|
||||||
|
"just_u16",
|
||||||
|
"maybe_u16",
|
||||||
|
"default_u16",
|
||||||
|
"just_i32",
|
||||||
|
"maybe_i32",
|
||||||
|
"default_i32",
|
||||||
|
"just_u32",
|
||||||
|
"maybe_u32",
|
||||||
|
"default_u32",
|
||||||
|
"just_i64",
|
||||||
|
"maybe_i64",
|
||||||
|
"default_i64",
|
||||||
|
"just_u64",
|
||||||
|
"maybe_u64",
|
||||||
|
"default_u64",
|
||||||
|
"just_f32",
|
||||||
|
"maybe_f32",
|
||||||
|
"default_f32",
|
||||||
|
"just_f64",
|
||||||
|
"maybe_f64",
|
||||||
|
"default_f64",
|
||||||
|
"just_bool",
|
||||||
|
"maybe_bool",
|
||||||
|
"default_bool",
|
||||||
|
"just_enum",
|
||||||
|
"maybe_enum",
|
||||||
|
"default_enum"
|
||||||
|
};
|
||||||
|
template<size_t Index>
|
||||||
|
using FieldType = decltype(std::declval<type>().get_field<Index>());
|
||||||
|
static constexpr size_t fields_number = 36;
|
||||||
};
|
};
|
||||||
|
|
||||||
flatbuffers::Offset<ScalarStuff> CreateScalarStuff(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
flatbuffers::Offset<ScalarStuff> CreateScalarStuff(flatbuffers::FlatBufferBuilder &_fbb, const ScalarStuffT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
|
|||||||
186
tests/cpp17/stringify_util.h
Normal file
186
tests/cpp17/stringify_util.h
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// This contains some utilities/examples for how to leverage the static reflec-
|
||||||
|
// tion features of tables and structs in the C++17 code generation to recur-
|
||||||
|
// sively produce a string representation of any Flatbuffer table or struct use
|
||||||
|
// compile-time iteration over the fields. Note that this code is completely
|
||||||
|
// generic in that it makes no reference to any particular Flatbuffer type.
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
#include "flatbuffers/util.h"
|
||||||
|
|
||||||
|
namespace cpp17 {
|
||||||
|
|
||||||
|
// User calls this; need to forward declare it since it is called recursively.
|
||||||
|
template<typename T>
|
||||||
|
std::optional<std::string> StringifyFlatbufferValue(
|
||||||
|
T &&val, const std::string &indent = "");
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Metaprogramming helpers for detecting Flatbuffers Tables, Structs, & Vectors.
|
||||||
|
*******************************************************************************/
|
||||||
|
template<typename FBS, typename = void>
|
||||||
|
struct is_flatbuffers_table_or_struct : std::false_type {};
|
||||||
|
|
||||||
|
// We know it's a table or struct when it has a Traits subclass.
|
||||||
|
template<typename FBS>
|
||||||
|
struct is_flatbuffers_table_or_struct<FBS, std::void_t<typename FBS::Traits>>
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
template<typename FBS>
|
||||||
|
inline constexpr bool is_flatbuffers_table_or_struct_v =
|
||||||
|
is_flatbuffers_table_or_struct<FBS>::value;
|
||||||
|
|
||||||
|
template<typename T> struct is_flatbuffers_vector : std::false_type {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct is_flatbuffers_vector<flatbuffers::Vector<T>> : std::true_type {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline constexpr bool is_flatbuffers_vector_v = is_flatbuffers_vector<T>::value;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Compile-time Iteration & Recursive Stringification over Flatbuffers types.
|
||||||
|
*******************************************************************************/
|
||||||
|
template<size_t Index, typename FBS>
|
||||||
|
std::string AddStringifiedField(const FBS &fbs, const std::string &indent) {
|
||||||
|
auto value_string =
|
||||||
|
StringifyFlatbufferValue(fbs.template get_field<Index>(), indent);
|
||||||
|
if (!value_string) { return ""; }
|
||||||
|
return indent + FBS::Traits::field_names[Index] + " = " + *value_string +
|
||||||
|
"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FBS, size_t... Indexes>
|
||||||
|
std::string StringifyTableOrStructImpl(const FBS &fbs,
|
||||||
|
const std::string &indent,
|
||||||
|
std::index_sequence<Indexes...>) {
|
||||||
|
// This line is where the compile-time iteration happens!
|
||||||
|
return (AddStringifiedField<Indexes>(fbs, indent) + ...);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FBS>
|
||||||
|
std::string StringifyTableOrStruct(const FBS &fbs, const std::string &indent) {
|
||||||
|
static constexpr size_t field_count = FBS::Traits::fields_number;
|
||||||
|
std::string out;
|
||||||
|
if constexpr (field_count > 0) {
|
||||||
|
out = std::string(FBS::Traits::fully_qualified_name) + "{\n" +
|
||||||
|
StringifyTableOrStructImpl(fbs, indent + " ",
|
||||||
|
std::make_index_sequence<field_count>{}) +
|
||||||
|
indent + '}';
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::string StringifyVector(const flatbuffers::Vector<T> &vec,
|
||||||
|
const std::string &indent) {
|
||||||
|
const auto prologue = indent + std::string(" ");
|
||||||
|
const auto epilogue = std::string(",\n");
|
||||||
|
std::string text;
|
||||||
|
text += "[\n";
|
||||||
|
for (auto it = vec.cbegin(), end = vec.cend(); it != end; ++it) {
|
||||||
|
text += prologue;
|
||||||
|
text += StringifyFlatbufferValue(*it).value_or("(field absent)");
|
||||||
|
text += epilogue;
|
||||||
|
}
|
||||||
|
if (vec.cbegin() != vec.cend()) {
|
||||||
|
text.resize(text.size() - epilogue.size());
|
||||||
|
}
|
||||||
|
text += '\n' + indent + ']';
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> std::string StringifyArithmeticType(T val) {
|
||||||
|
return flatbuffers::NumToString(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Take any flatbuffer type (table, struct, Vector, int...) and stringify it.
|
||||||
|
*******************************************************************************/
|
||||||
|
template<typename T>
|
||||||
|
std::optional<std::string> StringifyFlatbufferValue(T &&val,
|
||||||
|
const std::string &indent) {
|
||||||
|
constexpr bool is_pointer = std::is_pointer_v<std::remove_reference_t<T>>;
|
||||||
|
if constexpr (is_pointer) {
|
||||||
|
if (val == nullptr) return std::nullopt; // Field is absent.
|
||||||
|
}
|
||||||
|
using decayed =
|
||||||
|
std::decay_t<std::remove_pointer_t<std::remove_reference_t<T>>>;
|
||||||
|
|
||||||
|
// Is it a Flatbuffers Table or Struct?
|
||||||
|
if constexpr (detail::is_flatbuffers_table_or_struct_v<decayed>) {
|
||||||
|
// We have a nested table or struct; use recursion!
|
||||||
|
if constexpr (is_pointer)
|
||||||
|
return detail::StringifyTableOrStruct(*val, indent);
|
||||||
|
else
|
||||||
|
return detail::StringifyTableOrStruct(val, indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it an 8-bit number? If so, print it like an int (not char).
|
||||||
|
else if constexpr (std::is_same_v<decayed, int8_t> ||
|
||||||
|
std::is_same_v<decayed, uint8_t>) {
|
||||||
|
return detail::StringifyArithmeticType(static_cast<int>(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it an enum? If so, print it like an int, since Flatbuffers doesn't yet
|
||||||
|
// have type-based reflection for enums, so we can't print the enum's name :(
|
||||||
|
else if constexpr (std::is_enum_v<decayed>) {
|
||||||
|
return StringifyFlatbufferValue(
|
||||||
|
static_cast<std::underlying_type_t<decayed>>(val), indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it an int, double, float, uint32_t, etc.?
|
||||||
|
else if constexpr (std::is_arithmetic_v<decayed>) {
|
||||||
|
return detail::StringifyArithmeticType(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it a Flatbuffers string?
|
||||||
|
else if constexpr (std::is_same_v<decayed, flatbuffers::String>) {
|
||||||
|
return '"' + val->str() + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it a Flatbuffers Vector?
|
||||||
|
else if constexpr (detail::is_flatbuffers_vector_v<decayed>) {
|
||||||
|
return detail::StringifyVector(*val, indent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is it a void pointer?
|
||||||
|
else if constexpr (std::is_same_v<decayed, void>) {
|
||||||
|
// Can't format it.
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
// Not sure how to format this type, whatever it is.
|
||||||
|
static_assert(sizeof(T) != sizeof(T),
|
||||||
|
"Do not know how to format this type T (the compiler error "
|
||||||
|
"should tell you nearby what T is).");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cpp17
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
#include "flatbuffers/minireflect.h"
|
#include "flatbuffers/minireflect.h"
|
||||||
#include "flatbuffers/registry.h"
|
#include "flatbuffers/registry.h"
|
||||||
#include "flatbuffers/util.h"
|
#include "flatbuffers/util.h"
|
||||||
|
#include "stringify_util.h"
|
||||||
#include "test_assert.h"
|
#include "test_assert.h"
|
||||||
|
|
||||||
// Embed generated code into an isolated namespace.
|
// Embed generated code into an isolated namespace.
|
||||||
@@ -38,6 +39,144 @@ namespace cpp11 {
|
|||||||
#include "../optional_scalars_generated.h"
|
#include "../optional_scalars_generated.h"
|
||||||
} // namespace cpp11
|
} // namespace cpp11
|
||||||
|
|
||||||
|
using ::cpp17::MyGame::Example::Monster;
|
||||||
|
using ::cpp17::MyGame::Example::Vec3;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Build some FB objects.
|
||||||
|
*******************************************************************************/
|
||||||
|
const Monster *BuildMonster(flatbuffers::FlatBufferBuilder &fbb) {
|
||||||
|
using ::cpp17::MyGame::Example::Color;
|
||||||
|
using ::cpp17::MyGame::Example::MonsterBuilder;
|
||||||
|
using ::cpp17::MyGame::Example::Test;
|
||||||
|
auto name = fbb.CreateString("my_monster");
|
||||||
|
auto inventory = fbb.CreateVector(std::vector<uint8_t>{ 4, 5, 6, 7 });
|
||||||
|
MonsterBuilder builder(fbb);
|
||||||
|
auto vec3 = Vec3{ /*x=*/1.1f,
|
||||||
|
/*y=*/2.2f,
|
||||||
|
/*z=*/3.3f,
|
||||||
|
/*test1=*/6.6,
|
||||||
|
/*test2=*/Color::Green,
|
||||||
|
/*test3=*/
|
||||||
|
Test(
|
||||||
|
/*a=*/11,
|
||||||
|
/*b=*/90) };
|
||||||
|
builder.add_pos(&vec3);
|
||||||
|
builder.add_name(name);
|
||||||
|
builder.add_mana(1);
|
||||||
|
builder.add_hp(2);
|
||||||
|
builder.add_testbool(true);
|
||||||
|
builder.add_testhashs32_fnv1(4);
|
||||||
|
builder.add_testhashu32_fnv1(5);
|
||||||
|
builder.add_testhashs64_fnv1(6);
|
||||||
|
builder.add_testhashu64_fnv1(7);
|
||||||
|
builder.add_testhashs32_fnv1a(8);
|
||||||
|
builder.add_testhashu32_fnv1a(9);
|
||||||
|
builder.add_testhashs64_fnv1a(10);
|
||||||
|
builder.add_testhashu64_fnv1a(11);
|
||||||
|
builder.add_testf(12.1f);
|
||||||
|
builder.add_testf2(13.1f);
|
||||||
|
builder.add_testf3(14.1f);
|
||||||
|
builder.add_single_weak_reference(15);
|
||||||
|
builder.add_co_owning_reference(16);
|
||||||
|
builder.add_non_owning_reference(17);
|
||||||
|
builder.add_inventory(inventory);
|
||||||
|
fbb.Finish(builder.Finish());
|
||||||
|
const Monster *monster =
|
||||||
|
flatbuffers::GetRoot<Monster>(fbb.GetBufferPointer());
|
||||||
|
return monster;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Test Case: Static Field Reflection Traits for Table & Structs.
|
||||||
|
*******************************************************************************/
|
||||||
|
// This test tests & demonstrates the power of the static reflection. Using it,
|
||||||
|
// we can given any Flatbuffer type to a generic function and it will be able to
|
||||||
|
// produce is full recursive string representation of it.
|
||||||
|
//
|
||||||
|
// This test covers all types: primitive types, structs, tables, Vectors, etc.
|
||||||
|
//
|
||||||
|
void StringifyAnyFlatbuffersTypeTest() {
|
||||||
|
flatbuffers::FlatBufferBuilder fbb;
|
||||||
|
// We are using a Monster here, but we could have used any type, because the
|
||||||
|
// code that follows is totally generic!
|
||||||
|
const auto *monster = BuildMonster(fbb);
|
||||||
|
|
||||||
|
std::string expected = R"(MyGame.Example.Monster{
|
||||||
|
pos = MyGame.Example.Vec3{
|
||||||
|
x = 1.1
|
||||||
|
y = 2.2
|
||||||
|
z = 3.3
|
||||||
|
test1 = 6.6
|
||||||
|
test2 = 2
|
||||||
|
test3 = MyGame.Example.Test{
|
||||||
|
a = 11
|
||||||
|
b = 90
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mana = 1
|
||||||
|
hp = 2
|
||||||
|
name = "my_monster"
|
||||||
|
inventory = [
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7
|
||||||
|
]
|
||||||
|
color = 8
|
||||||
|
test_type = 0
|
||||||
|
testbool = 1
|
||||||
|
testhashs32_fnv1 = 4
|
||||||
|
testhashu32_fnv1 = 5
|
||||||
|
testhashs64_fnv1 = 6
|
||||||
|
testhashu64_fnv1 = 7
|
||||||
|
testhashs32_fnv1a = 8
|
||||||
|
testhashu32_fnv1a = 9
|
||||||
|
testhashs64_fnv1a = 10
|
||||||
|
testhashu64_fnv1a = 11
|
||||||
|
testf = 12.1
|
||||||
|
testf2 = 13.1
|
||||||
|
testf3 = 14.1
|
||||||
|
single_weak_reference = 15
|
||||||
|
co_owning_reference = 16
|
||||||
|
non_owning_reference = 17
|
||||||
|
any_unique_type = 0
|
||||||
|
any_ambiguous_type = 0
|
||||||
|
signed_enum = -1
|
||||||
|
})";
|
||||||
|
|
||||||
|
// Call a generic function that has no specific knowledge of the flatbuffer we
|
||||||
|
// are passing in; it should use only static reflection to produce a string
|
||||||
|
// representations of the field names and values recursively. We give it an
|
||||||
|
// initial indentation so that the result can be compared with our raw string
|
||||||
|
// above, which we wanted to indent so that it will look nicer in this code.
|
||||||
|
//
|
||||||
|
// A note about JSON: as can be seen from the string above, this produces a
|
||||||
|
// JSON-like notation, but we are not using any of Flatbuffers' JSON infra to
|
||||||
|
// produce this! It is produced entirely using compile-time reflection, and
|
||||||
|
// thus does not require any runtime access to the *.fbs definition files!
|
||||||
|
std::optional<std::string> result =
|
||||||
|
cpp17::StringifyFlatbufferValue(*monster, /*indent=*/" ");
|
||||||
|
|
||||||
|
TEST_ASSERT(result.has_value());
|
||||||
|
TEST_EQ_STR(expected.c_str(), result->c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Test Traits::FieldType
|
||||||
|
*******************************************************************************/
|
||||||
|
using pos_type = Monster::Traits::FieldType<0>;
|
||||||
|
static_assert(std::is_same_v<pos_type, const Vec3*>);
|
||||||
|
|
||||||
|
using mana_type = Monster::Traits::FieldType<1>;
|
||||||
|
static_assert(std::is_same_v<mana_type, int16_t>);
|
||||||
|
|
||||||
|
using name_type = Monster::Traits::FieldType<3>;
|
||||||
|
static_assert(std::is_same_v<name_type, const flatbuffers::String*>);
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Generic Create Function Test.
|
||||||
|
*******************************************************************************/
|
||||||
void CreateTableByTypeTest() {
|
void CreateTableByTypeTest() {
|
||||||
flatbuffers::FlatBufferBuilder builder;
|
flatbuffers::FlatBufferBuilder builder;
|
||||||
|
|
||||||
@@ -62,7 +201,8 @@ void CreateTableByTypeTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OptionalScalarsTest() {
|
void OptionalScalarsTest() {
|
||||||
static_assert(std::is_same<flatbuffers::Optional<float>, std::optional<float>>::value);
|
static_assert(
|
||||||
|
std::is_same<flatbuffers::Optional<float>, std::optional<float>>::value);
|
||||||
static_assert(std::is_same<flatbuffers::nullopt_t, std::nullopt_t>::value);
|
static_assert(std::is_same<flatbuffers::nullopt_t, std::nullopt_t>::value);
|
||||||
|
|
||||||
// test C++ nullable
|
// test C++ nullable
|
||||||
@@ -105,6 +245,7 @@ void OptionalScalarsTest() {
|
|||||||
int FlatBufferCpp17Tests() {
|
int FlatBufferCpp17Tests() {
|
||||||
CreateTableByTypeTest();
|
CreateTableByTypeTest();
|
||||||
OptionalScalarsTest();
|
OptionalScalarsTest();
|
||||||
|
StringifyAnyFlatbuffersTypeTest();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Flag c++17 requires Clang6, GCC7, MSVC2017 (_MSC_VER >= 1914) or higher.
|
# Flag c++17 requires Clang6, GCC7, MSVC2017 (_MSC_VER >= 1914) or higher.
|
||||||
TEST_CPP17_FLAGS="--cpp --cpp-std c++17 -o ./cpp17/generated_cpp17 $TEST_NOINCL_FLAGS"
|
TEST_CPP17_FLAGS="--cpp --cpp-std c++17 --cpp-static-reflection -o ./cpp17/generated_cpp17 $TEST_NOINCL_FLAGS"
|
||||||
../flatc $TEST_CPP17_FLAGS -I include_test monster_test.fbs
|
../flatc $TEST_CPP17_FLAGS -I include_test monster_test.fbs
|
||||||
../flatc $TEST_CPP17_FLAGS optional_scalars.fbs
|
../flatc $TEST_CPP17_FLAGS optional_scalars.fbs
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user