mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 04:04:19 +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_ += " }";
|
||||
|
||||
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 (is_scalar) {
|
||||
code_.SetValue("OFFSET_NAME", offset_str);
|
||||
@@ -1222,6 +1254,44 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += "};"; // End of table.
|
||||
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);
|
||||
|
||||
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 {
|
||||
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() {
|
||||
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);
|
||||
};
|
||||
|
||||
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 {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
|
||||
Reference in New Issue
Block a user