mirror of
https://github.com/google/flatbuffers.git
synced 2026-07-02 03:33:57 +00:00
[C++] Additional accessors for fields of union types. (#4184)
* Additional accessors for fields of union types. * Reveal the hidden parameter. * External explicit specializations for templated accessors. * Changes according to code style. Generated code included as well.
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
ebcfbbadf0
commit
037314a059
@@ -1118,6 +1118,38 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code_ += " return {{FIELD_VALUE}};";
|
code_ += " return {{FIELD_VALUE}};";
|
||||||
code_ += " }";
|
code_ += " }";
|
||||||
|
|
||||||
|
if (field.value.type.base_type == BASE_TYPE_UNION) {
|
||||||
|
auto u = field.value.type.enum_def;
|
||||||
|
|
||||||
|
code_ += " template<typename T> "
|
||||||
|
"const T *{{FIELD_NAME}}_as() const;";
|
||||||
|
|
||||||
|
for (auto u_it = u->vals.vec.begin();
|
||||||
|
u_it != u->vals.vec.end(); ++u_it) {
|
||||||
|
if (!(*u_it)->struct_def) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto arg_struct_def = (*u_it)->struct_def;
|
||||||
|
auto full_struct_name = WrapInNameSpace(*arg_struct_def);
|
||||||
|
|
||||||
|
// @TODO: Mby make this decisions more universal? How?
|
||||||
|
code_.SetValue("U_GET_TYPE", field.name + UnionTypeFieldSuffix());
|
||||||
|
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(
|
||||||
|
u->defined_namespace, GetEnumValUse(*u, **u_it)));
|
||||||
|
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
|
||||||
|
code_.SetValue("U_ELEMENT_NAME", full_struct_name);
|
||||||
|
code_.SetValue("U_FIELD_NAME",
|
||||||
|
field.name + "_as_" + (*u_it)->name);
|
||||||
|
|
||||||
|
// `const Type *union_name_asType() const` accessor.
|
||||||
|
code_ += " {{U_FIELD_TYPE}}{{U_FIELD_NAME}}() const {";
|
||||||
|
code_ += " return ({{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}})? "
|
||||||
|
"static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) "
|
||||||
|
": nullptr;";
|
||||||
|
code_ += " }";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (parser_.opts.mutable_buffer) {
|
if (parser_.opts.mutable_buffer) {
|
||||||
if (is_scalar) {
|
if (is_scalar) {
|
||||||
code_.SetValue("OFFSET_NAME", offset_str);
|
code_.SetValue("OFFSET_NAME", offset_str);
|
||||||
@@ -1222,6 +1254,44 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code_ += "};"; // End of table.
|
code_ += "};"; // End of table.
|
||||||
code_ += "";
|
code_ += "";
|
||||||
|
|
||||||
|
// Explicit specializations for union accessors
|
||||||
|
for (auto it = struct_def.fields.vec.begin();
|
||||||
|
it != struct_def.fields.vec.end(); ++it) {
|
||||||
|
const auto &field = **it;
|
||||||
|
if (field.deprecated ||
|
||||||
|
field.value.type.base_type != BASE_TYPE_UNION) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto u = field.value.type.enum_def;
|
||||||
|
code_.SetValue("FIELD_NAME", field.name);
|
||||||
|
|
||||||
|
for (auto u_it = u->vals.vec.begin();
|
||||||
|
u_it != u->vals.vec.end(); ++u_it) {
|
||||||
|
if (!(*u_it)->struct_def) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto arg_struct_def = (*u_it)->struct_def;
|
||||||
|
auto full_struct_name = WrapInNameSpace(*arg_struct_def);
|
||||||
|
|
||||||
|
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(
|
||||||
|
u->defined_namespace, GetEnumValUse(*u, **u_it)));
|
||||||
|
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
|
||||||
|
code_.SetValue("U_ELEMENT_NAME", full_struct_name);
|
||||||
|
code_.SetValue("U_FIELD_NAME",
|
||||||
|
field.name + "_as_" + (*u_it)->name);
|
||||||
|
|
||||||
|
// `template<> const T *union_name_as<T>() const` accessor.
|
||||||
|
code_ += "template<> "
|
||||||
|
"inline {{U_FIELD_TYPE}}{{STRUCT_NAME}}::{{FIELD_NAME}}_as"
|
||||||
|
"<{{U_ELEMENT_NAME}}>() const {";
|
||||||
|
code_ += " return {{U_FIELD_NAME}}();";
|
||||||
|
code_ += "}";
|
||||||
|
code_ += "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GenBuilders(struct_def);
|
GenBuilders(struct_def);
|
||||||
|
|
||||||
if (parser_.opts.generate_object_based_api) {
|
if (parser_.opts.generate_object_based_api) {
|
||||||
|
|||||||
Binary file not shown.
@@ -582,6 +582,16 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
const void *test() const {
|
const void *test() const {
|
||||||
return GetPointer<const void *>(VT_TEST);
|
return GetPointer<const void *>(VT_TEST);
|
||||||
}
|
}
|
||||||
|
template<typename T> const T *test_as() const;
|
||||||
|
const Monster *test_as_Monster() const {
|
||||||
|
return (test_type() == Any_Monster)? static_cast<const Monster *>(test()) : nullptr;
|
||||||
|
}
|
||||||
|
const TestSimpleTableWithEnum *test_as_TestSimpleTableWithEnum() const {
|
||||||
|
return (test_type() == Any_TestSimpleTableWithEnum)? static_cast<const TestSimpleTableWithEnum *>(test()) : nullptr;
|
||||||
|
}
|
||||||
|
const MyGame::Example2::Monster *test_as_MyGame_Example2_Monster() const {
|
||||||
|
return (test_type() == Any_MyGame_Example2_Monster)? static_cast<const MyGame::Example2::Monster *>(test()) : nullptr;
|
||||||
|
}
|
||||||
void *mutable_test() {
|
void *mutable_test() {
|
||||||
return GetPointer<void *>(VT_TEST);
|
return GetPointer<void *>(VT_TEST);
|
||||||
}
|
}
|
||||||
@@ -762,6 +772,18 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
static flatbuffers::Offset<Monster> Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
static flatbuffers::Offset<Monster> Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<> inline const Monster *Monster::test_as<Monster>() const {
|
||||||
|
return test_as_Monster();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline const TestSimpleTableWithEnum *Monster::test_as<TestSimpleTableWithEnum>() const {
|
||||||
|
return test_as_TestSimpleTableWithEnum();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline const MyGame::Example2::Monster *Monster::test_as<MyGame::Example2::Monster>() const {
|
||||||
|
return test_as_MyGame_Example2_Monster();
|
||||||
|
}
|
||||||
|
|
||||||
struct MonsterBuilder {
|
struct MonsterBuilder {
|
||||||
flatbuffers::FlatBufferBuilder &fbb_;
|
flatbuffers::FlatBufferBuilder &fbb_;
|
||||||
flatbuffers::uoffset_t start_;
|
flatbuffers::uoffset_t start_;
|
||||||
|
|||||||
Reference in New Issue
Block a user