Commit 037314a0 authored by Franken's avatar Franken Committed by Wouter van Oortmerssen

[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.
parent ebcfbbad
...@@ -1118,6 +1118,38 @@ class CppGenerator : public BaseGenerator { ...@@ -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 { ...@@ -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) {
......
No preview for this file type
...@@ -582,6 +582,16 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { ...@@ -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 { ...@@ -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_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment