From 037314a05978f2b4ae807c1106ba7a2d7b439425 Mon Sep 17 00:00:00 2001 From: Franken Date: Sun, 26 Feb 2017 07:23:32 +0200 Subject: [PATCH] [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. --- src/idl_gen_cpp.cpp | 70 +++++++++++++++++++++++++++++++++ tests/monster_test.bfbs | Bin 3904 -> 3368 bytes tests/monster_test_generated.h | 22 +++++++++++ 3 files changed, 92 insertions(+) diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 86cadd320..1e53088e4 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -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 " + "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() 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) { diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs index 21f3c0008fc9a5632ea6aa2c6667f93251da08eb..8df32d9d59be351256df1f63be91f72a9c2ddee0 100644 GIT binary patch literal 3368 zcmaJ^UuauZ82{2HX_BUY*3GVFab%;6GD_&$QlyB~x^^hG9c!I?C@VMZjmb!ELUL2q z;zJ)~?5Phvh!hbS!v`OH@JWiu5E)~PK8R04e2_8r;Dd-vH|OH-cg{V@B?}(-a?ZWq z@B7a8?|kG!qz#fXs73{ zTE%j~PQT%7X?@><_X%hPMA`J?dL0vX6S-Tj*J<}X*v9?LIEsbVx8~^^Ut1_SRoAY7 z6H~s&;XT|@ekZYjn~g#F6}###=V{A|l_}Wo<=xzzQ!9cKgG>+}X?fbT3Tu=>STkm3 zuV0?m>x>C$acOZ5lbnam^nDma-)Vn~?{Ah0B^s)H%3)?sxXsRREy9me( z?lW7c*~Uil=p%7{|3Y{^SFvpe+L1tr&E{3M+G3G@KZ@vz9}SdU>I!}Bxn&to2e!f&vif!qg}@4%?vKo9WD zn!5!05YM-OOJcr+`7Gug%s+#MK#%Y|jl3k0CB~6HvYuVkk5#EyTcvE(t>m5e$3=FZ zF@L>1SAahz(+bbrz$}H&PQYL0xH|zoJT*bZBgTvb772M(*R6Rekr^%y=akht{re zcCqZD{mR}y%D+C8xg3W~j~rLn6rQP4X7t+$UdUqObQoHE0p78!l!&`lyZ73|6E zD?EGjJ&GO;i@`+a2f&gDwJ zRLQH7QP?vIE0V3`ZD*svbjwrv-;sb{{=Mm|-e2z>2z0_q>NK%-@I9gYp7yurK5C!? z2=W=D4Kgv9t6W(m!<>ZteecEi22_M~{y$dI+RvipSbPlQyNxN7QT3+3kMtj(2q~AU z^0nsoF*e_0Kk`x_#_2Gq<@>bkTCS2Mj`og#*emIW@m1%x=D6Tp)B3|70Yh7fG5c@g zqd3o4L=!59e9yk`A3ByzyBV82Hs*Z<%bsaH2N;=Q5a$%AjqMlh^$DdPp>5nl?qGcr zv;&%gu8?wy=+7*6(!@!>5)>*URv9_V`qrbb?= zD+p?nSK6%3%qsXP5N%{nFn131%KM>>0igYH%;4PtFEZ~hyMryCbO@F~IW-28{pj05$If~bdmvHd;uU8h#XMb{hu E0WG9er2qf` literal 3904 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 P@&A;UgL(~rb`tGBDj=Xf diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index ee9453650..ce952e1a7 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -582,6 +582,16 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const void *test() const { return GetPointer(VT_TEST); } + template const T *test_as() const; + const Monster *test_as_Monster() const { + return (test_type() == Any_Monster)? static_cast(test()) : nullptr; + } + const TestSimpleTableWithEnum *test_as_TestSimpleTableWithEnum() const { + return (test_type() == Any_TestSimpleTableWithEnum)? static_cast(test()) : nullptr; + } + const MyGame::Example2::Monster *test_as_MyGame_Example2_Monster() const { + return (test_type() == Any_MyGame_Example2_Monster)? static_cast(test()) : nullptr; + } void *mutable_test() { return GetPointer(VT_TEST); } @@ -762,6 +772,18 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); }; +template<> inline const Monster *Monster::test_as() const { + return test_as_Monster(); +} + +template<> inline const TestSimpleTableWithEnum *Monster::test_as() const { + return test_as_TestSimpleTableWithEnum(); +} + +template<> inline const MyGame::Example2::Monster *Monster::test_as() const { + return test_as_MyGame_Example2_Monster(); +} + struct MonsterBuilder { flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::uoffset_t start_;