C++ Feature: Mutable union getters (#8852)

* generate mutable union accessors

* add test

* Revert "add test"

This reverts commit 45e352b18f93c9d59afef6498f9948b2dcb8c0a4.

* update file

* formatter got in the way

* merge conflicts

* updated genned code

* manually fix code gen bc I can't figure out why this file won't code gen

---------

Co-authored-by: Wouter van Oortmerssen <aardappel@gmail.com>
diff --git a/samples/monster_generated.h b/samples/monster_generated.h
index 7e3ed6b..9cf1abd 100644
--- a/samples/monster_generated.h
+++ b/samples/monster_generated.h
@@ -328,6 +328,10 @@
   const MyGame::Sample::Weapon *equipped_as_Weapon() const {
     return equipped_type() == MyGame::Sample::Equipment_Weapon ? static_cast<const MyGame::Sample::Weapon *>(equipped()) : nullptr;
   }
+  template<typename T> T *mutable_equipped_as();
+  MyGame::Sample::Weapon *mutable_equipped_as_Weapon() {
+    return equipped_type() == MyGame::Sample::Equipment_Weapon ? static_cast<MyGame::Sample::Weapon *>(mutable_equipped()) : nullptr;
+  }
   void *mutable_equipped() {
     return GetPointer<void *>(VT_EQUIPPED);
   }
@@ -367,6 +371,10 @@
   return equipped_as_Weapon();
 }
 
+template<> inline MyGame::Sample::Weapon *Monster::mutable_equipped_as<MyGame::Sample::Weapon>() {
+  return mutable_equipped_as_Weapon();
+}
+
 struct MonsterBuilder {
   typedef Monster Table;
   ::flatbuffers::FlatBufferBuilder &fbb_;
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index f6e61ff..51bb820 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -2685,14 +2685,18 @@
     code_ += "  }";
   }
 
-  void GenTableUnionAsGetters(const FieldDef& field) {
+  void GenTableUnionAsGetters(const FieldDef& field, bool is_mutable) {
     const auto& type = field.value.type;
     auto u = type.enum_def;
 
+    code_.SetValue("MUTABLE_EXT", is_mutable ? "" : " const");
+    code_.SetValue("MUTABLE", is_mutable ? "mutable_" : "");
+
     if (!type.enum_def->uses_multiple_type_instances)
       code_ +=
-          "  template<typename T> "
-          "const T *{{NULLABLE_EXT}}{{FIELD_NAME}}_as() const;";
+          "  template<typename T>"
+          "{{MUTABLE_EXT}} T *{{MUTABLE}}{{NULLABLE_EXT}}{{FIELD_NAME}}_as()"
+          "{{MUTABLE_EXT}};";
 
     for (auto u_it = u->Vals().begin(); u_it != u->Vals().end(); ++u_it) {
       auto& ev = **u_it;
@@ -2706,15 +2710,19 @@
                      EscapeKeyword(Name(field) + UnionTypeFieldSuffix()));
       code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(u->defined_namespace,
                                                        GetEnumValUse(*u, ev)));
-      code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
+      code_.SetValue("U_FIELD_TYPE",
+                     (is_mutable ? "" : "const ") + full_struct_name + " *");
       code_.SetValue("U_FIELD_NAME", Name(field) + "_as_" + Name(ev));
       code_.SetValue("U_NULLABLE", NullableExtension());
 
       // `const Type *union_name_asType() const` accessor.
-      code_ += "  {{U_FIELD_TYPE}}{{U_NULLABLE}}{{U_FIELD_NAME}}() const {";
+      // and `Type *mutable_union_name_asType()` accessor.
+      code_ +=
+          "  {{U_FIELD_TYPE}}{{U_NULLABLE}}{{MUTABLE}}{{U_FIELD_NAME}}()"
+          "{{MUTABLE_EXT}} {";
       code_ +=
           "    return {{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}} ? "
-          "static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) "
+          "static_cast<{{U_FIELD_TYPE}}>({{MUTABLE}}{{FIELD_NAME}}()) "
           ": nullptr;";
       code_ += "  }";
     }
@@ -2755,7 +2763,7 @@
       code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, call));
       code_.SetValue("NULLABLE_EXT", NullableExtension());
       code_ += "  {{FIELD_TYPE}}{{FIELD_NAME}}() const {";
-            if (IsVector(type) && field.value.constant == "[]") {
+      if (IsVector(type) && field.value.constant == "[]") {
         const auto& vec_type = type.VectorType();
         const std::string vtype_wire = GenTypeWire(
             vec_type, "", VectorElementUserFacing(vec_type), field.offset64);
@@ -2799,7 +2807,7 @@
     }
 
     if (type.base_type == BASE_TYPE_UNION) {
-      GenTableUnionAsGetters(field);
+      GenTableUnionAsGetters(field, false);
     }
   }
 
@@ -2974,6 +2982,11 @@
       auto wire_type = GenTypeGet(type, " ", "", postptr.c_str(), true);
       code_.SetValue("FIELD_TYPE", wire_type);
 
+      // mutable union accessors
+      if (type.base_type == BASE_TYPE_UNION) {
+        GenTableUnionAsGetters(field, true);
+      }
+
       if (IsVector(type) && field.value.constant == "[]") {
         const auto& vec_type = type.VectorType();
         const std::string vtype_wire = GenTypeWire(
@@ -3185,6 +3198,7 @@
         code_.SetValue("U_FIELD_NAME", Name(*field) + "_as_" + Name(ev));
 
         // `template<> const T *union_name_as<T>() const` accessor.
+        // and `template<> T *mutable_union_name_as<T>()` accessor.
         code_ +=
             "template<> "
             "inline {{U_FIELD_TYPE}}{{STRUCT_NAME}}::{{FIELD_NAME}}_as"
@@ -3192,6 +3206,20 @@
         code_ += "  return {{U_FIELD_NAME}}();";
         code_ += "}";
         code_ += "";
+
+        if (opts_.mutable_buffer) {
+          code_.SetValue("U_FIELD_TYPE", full_struct_name + " *");
+          code_.SetValue("U_FIELD_NAME",
+                         "mutable_" + Name(*field) + "_as_" + Name(ev));
+          code_ +=
+              "template<> "
+              "inline {{U_FIELD_TYPE}}"
+              "{{STRUCT_NAME}}::mutable_{{FIELD_NAME}}_as"
+              "<{{U_ELEMENT_NAME}}>() {";
+          code_ += "  return {{U_FIELD_NAME}}();";
+          code_ += "}";
+          code_ += "";
+        }
       }
     }
 
diff --git a/tests/cpp17/generated_cpp17/monster_test_generated.h b/tests/cpp17/generated_cpp17/monster_test_generated.h
index f327c45..bb6efe1 100644
--- a/tests/cpp17/generated_cpp17/monster_test_generated.h
+++ b/tests/cpp17/generated_cpp17/monster_test_generated.h
@@ -1481,6 +1481,16 @@
   const MyGame::Example2::Monster *test_as_MyGame_Example2_Monster() const {
     return test_type() == MyGame::Example::Any::MyGame_Example2_Monster ? static_cast<const MyGame::Example2::Monster *>(test()) : nullptr;
   }
+  template<typename T> T *mutable_test_as();
+  MyGame::Example::Monster *mutable_test_as_Monster() {
+    return test_type() == MyGame::Example::Any::Monster ? static_cast<MyGame::Example::Monster *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_test_as_TestSimpleTableWithEnum() {
+    return test_type() == MyGame::Example::Any::TestSimpleTableWithEnum ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_test_as_MyGame_Example2_Monster() {
+    return test_type() == MyGame::Example::Any::MyGame_Example2_Monster ? static_cast<MyGame::Example2::Monster *>(mutable_test()) : nullptr;
+  }
   void *mutable_test() {
     return GetPointer<void *>(VT_TEST);
   }
@@ -1716,6 +1726,16 @@
   const MyGame::Example2::Monster *any_unique_as_M2() const {
     return any_unique_type() == MyGame::Example::AnyUniqueAliases::M2 ? static_cast<const MyGame::Example2::Monster *>(any_unique()) : nullptr;
   }
+  template<typename T> T *mutable_any_unique_as();
+  MyGame::Example::Monster *mutable_any_unique_as_M() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases::M ? static_cast<MyGame::Example::Monster *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_any_unique_as_TS() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases::TS ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_any_unique_as_M2() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases::M2 ? static_cast<MyGame::Example2::Monster *>(mutable_any_unique()) : nullptr;
+  }
   void *mutable_any_unique() {
     return GetPointer<void *>(VT_ANY_UNIQUE);
   }
@@ -1734,6 +1754,15 @@
   const MyGame::Example::Monster *any_ambiguous_as_M3() const {
     return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases::M3 ? static_cast<const MyGame::Example::Monster *>(any_ambiguous()) : nullptr;
   }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M1() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases::M1 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M2() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases::M2 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M3() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases::M3 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
   void *mutable_any_ambiguous() {
     return GetPointer<void *>(VT_ANY_AMBIGUOUS);
   }
@@ -2008,26 +2037,50 @@
   return test_as_Monster();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_test_as<MyGame::Example::Monster>() {
+  return mutable_test_as_Monster();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::test_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return test_as_TestSimpleTableWithEnum();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_test_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_test_as_TestSimpleTableWithEnum();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::test_as<MyGame::Example2::Monster>() const {
   return test_as_MyGame_Example2_Monster();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_test_as<MyGame::Example2::Monster>() {
+  return mutable_test_as_MyGame_Example2_Monster();
+}
+
 template<> inline const MyGame::Example::Monster *Monster::any_unique_as<MyGame::Example::Monster>() const {
   return any_unique_as_M();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_any_unique_as<MyGame::Example::Monster>() {
+  return mutable_any_unique_as_M();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return any_unique_as_TS();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_any_unique_as_TS();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::any_unique_as<MyGame::Example2::Monster>() const {
   return any_unique_as_M2();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_any_unique_as<MyGame::Example2::Monster>() {
+  return mutable_any_unique_as_M2();
+}
+
 struct MonsterBuilder {
   typedef Monster Table;
   ::flatbuffers::FlatBufferBuilder &fbb_;
diff --git a/tests/cpp17/generated_cpp17/union_vector_generated.h b/tests/cpp17/generated_cpp17/union_vector_generated.h
index 5e82fb2..a5e420b 100644
--- a/tests/cpp17/generated_cpp17/union_vector_generated.h
+++ b/tests/cpp17/generated_cpp17/union_vector_generated.h
@@ -595,6 +595,24 @@
   const ::flatbuffers::String *main_character_as_Unused() const {
     return main_character_type() == Character::Unused ? static_cast<const ::flatbuffers::String *>(main_character()) : nullptr;
   }
+  Attacker *mutable_main_character_as_MuLan() {
+    return main_character_type() == Character::MuLan ? static_cast<Attacker *>(mutable_main_character()) : nullptr;
+  }
+  Rapunzel *mutable_main_character_as_Rapunzel() {
+    return main_character_type() == Character::Rapunzel ? static_cast<Rapunzel *>(mutable_main_character()) : nullptr;
+  }
+  BookReader *mutable_main_character_as_Belle() {
+    return main_character_type() == Character::Belle ? static_cast<BookReader *>(mutable_main_character()) : nullptr;
+  }
+  BookReader *mutable_main_character_as_BookFan() {
+    return main_character_type() == Character::BookFan ? static_cast<BookReader *>(mutable_main_character()) : nullptr;
+  }
+  ::flatbuffers::String *mutable_main_character_as_Other() {
+    return main_character_type() == Character::Other ? static_cast<::flatbuffers::String *>(mutable_main_character()) : nullptr;
+  }
+  ::flatbuffers::String *mutable_main_character_as_Unused() {
+    return main_character_type() == Character::Unused ? static_cast<::flatbuffers::String *>(mutable_main_character()) : nullptr;
+  }
   void *mutable_main_character() {
     return GetPointer<void *>(VT_MAIN_CHARACTER);
   }
diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h
index d615176..7c994e5 100644
--- a/tests/monster_test_generated.h
+++ b/tests/monster_test_generated.h
@@ -1497,6 +1497,16 @@
   const MyGame::Example2::Monster *test_as_MyGame_Example2_Monster() const {
     return test_type() == MyGame::Example::Any_MyGame_Example2_Monster ? static_cast<const MyGame::Example2::Monster *>(test()) : nullptr;
   }
+  template<typename T> T *mutable_test_as();
+  MyGame::Example::Monster *mutable_test_as_Monster() {
+    return test_type() == MyGame::Example::Any_Monster ? static_cast<MyGame::Example::Monster *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_test_as_TestSimpleTableWithEnum() {
+    return test_type() == MyGame::Example::Any_TestSimpleTableWithEnum ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_test_as_MyGame_Example2_Monster() {
+    return test_type() == MyGame::Example::Any_MyGame_Example2_Monster ? static_cast<MyGame::Example2::Monster *>(mutable_test()) : nullptr;
+  }
   void *mutable_test() {
     return GetPointer<void *>(VT_TEST);
   }
@@ -1732,6 +1742,16 @@
   const MyGame::Example2::Monster *any_unique_as_M2() const {
     return any_unique_type() == MyGame::Example::AnyUniqueAliases_M2 ? static_cast<const MyGame::Example2::Monster *>(any_unique()) : nullptr;
   }
+  template<typename T> T *mutable_any_unique_as();
+  MyGame::Example::Monster *mutable_any_unique_as_M() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_M ? static_cast<MyGame::Example::Monster *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_any_unique_as_TS() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_TS ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_any_unique_as_M2() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_M2 ? static_cast<MyGame::Example2::Monster *>(mutable_any_unique()) : nullptr;
+  }
   void *mutable_any_unique() {
     return GetPointer<void *>(VT_ANY_UNIQUE);
   }
@@ -1750,6 +1770,15 @@
   const MyGame::Example::Monster *any_ambiguous_as_M3() const {
     return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M3 ? static_cast<const MyGame::Example::Monster *>(any_ambiguous()) : nullptr;
   }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M1() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M1 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M2() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M2 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M3() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M3 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
   void *mutable_any_ambiguous() {
     return GetPointer<void *>(VT_ANY_AMBIGUOUS);
   }
@@ -1959,26 +1988,50 @@
   return test_as_Monster();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_test_as<MyGame::Example::Monster>() {
+  return mutable_test_as_Monster();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::test_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return test_as_TestSimpleTableWithEnum();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_test_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_test_as_TestSimpleTableWithEnum();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::test_as<MyGame::Example2::Monster>() const {
   return test_as_MyGame_Example2_Monster();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_test_as<MyGame::Example2::Monster>() {
+  return mutable_test_as_MyGame_Example2_Monster();
+}
+
 template<> inline const MyGame::Example::Monster *Monster::any_unique_as<MyGame::Example::Monster>() const {
   return any_unique_as_M();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_any_unique_as<MyGame::Example::Monster>() {
+  return mutable_any_unique_as_M();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return any_unique_as_TS();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_any_unique_as_TS();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::any_unique_as<MyGame::Example2::Monster>() const {
   return any_unique_as_M2();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_any_unique_as<MyGame::Example2::Monster>() {
+  return mutable_any_unique_as_M2();
+}
+
 struct MonsterBuilder {
   typedef Monster Table;
   ::flatbuffers::FlatBufferBuilder &fbb_;
diff --git a/tests/monster_test_suffix/ext_only/monster_test_generated.hpp b/tests/monster_test_suffix/ext_only/monster_test_generated.hpp
index d478d89..91c5e32 100644
--- a/tests/monster_test_suffix/ext_only/monster_test_generated.hpp
+++ b/tests/monster_test_suffix/ext_only/monster_test_generated.hpp
@@ -1488,6 +1488,16 @@
   const MyGame::Example2::Monster *test_as_MyGame_Example2_Monster() const {
     return test_type() == MyGame::Example::Any_MyGame_Example2_Monster ? static_cast<const MyGame::Example2::Monster *>(test()) : nullptr;
   }
+  template<typename T> T *mutable_test_as();
+  MyGame::Example::Monster *mutable_test_as_Monster() {
+    return test_type() == MyGame::Example::Any_Monster ? static_cast<MyGame::Example::Monster *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_test_as_TestSimpleTableWithEnum() {
+    return test_type() == MyGame::Example::Any_TestSimpleTableWithEnum ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_test_as_MyGame_Example2_Monster() {
+    return test_type() == MyGame::Example::Any_MyGame_Example2_Monster ? static_cast<MyGame::Example2::Monster *>(mutable_test()) : nullptr;
+  }
   void *mutable_test() {
     return GetPointer<void *>(VT_TEST);
   }
@@ -1723,6 +1733,16 @@
   const MyGame::Example2::Monster *any_unique_as_M2() const {
     return any_unique_type() == MyGame::Example::AnyUniqueAliases_M2 ? static_cast<const MyGame::Example2::Monster *>(any_unique()) : nullptr;
   }
+  template<typename T> T *mutable_any_unique_as();
+  MyGame::Example::Monster *mutable_any_unique_as_M() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_M ? static_cast<MyGame::Example::Monster *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_any_unique_as_TS() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_TS ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_any_unique_as_M2() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_M2 ? static_cast<MyGame::Example2::Monster *>(mutable_any_unique()) : nullptr;
+  }
   void *mutable_any_unique() {
     return GetPointer<void *>(VT_ANY_UNIQUE);
   }
@@ -1741,6 +1761,15 @@
   const MyGame::Example::Monster *any_ambiguous_as_M3() const {
     return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M3 ? static_cast<const MyGame::Example::Monster *>(any_ambiguous()) : nullptr;
   }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M1() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M1 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M2() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M2 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M3() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M3 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
   void *mutable_any_ambiguous() {
     return GetPointer<void *>(VT_ANY_AMBIGUOUS);
   }
@@ -1950,26 +1979,50 @@
   return test_as_Monster();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_test_as<MyGame::Example::Monster>() {
+  return mutable_test_as_Monster();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::test_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return test_as_TestSimpleTableWithEnum();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_test_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_test_as_TestSimpleTableWithEnum();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::test_as<MyGame::Example2::Monster>() const {
   return test_as_MyGame_Example2_Monster();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_test_as<MyGame::Example2::Monster>() {
+  return mutable_test_as_MyGame_Example2_Monster();
+}
+
 template<> inline const MyGame::Example::Monster *Monster::any_unique_as<MyGame::Example::Monster>() const {
   return any_unique_as_M();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_any_unique_as<MyGame::Example::Monster>() {
+  return mutable_any_unique_as_M();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return any_unique_as_TS();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_any_unique_as_TS();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::any_unique_as<MyGame::Example2::Monster>() const {
   return any_unique_as_M2();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_any_unique_as<MyGame::Example2::Monster>() {
+  return mutable_any_unique_as_M2();
+}
+
 struct MonsterBuilder {
   typedef Monster Table;
   ::flatbuffers::FlatBufferBuilder &fbb_;
diff --git a/tests/monster_test_suffix/filesuffix_only/monster_test_suffix.h b/tests/monster_test_suffix/filesuffix_only/monster_test_suffix.h
index d478d89..91c5e32 100644
--- a/tests/monster_test_suffix/filesuffix_only/monster_test_suffix.h
+++ b/tests/monster_test_suffix/filesuffix_only/monster_test_suffix.h
@@ -1488,6 +1488,16 @@
   const MyGame::Example2::Monster *test_as_MyGame_Example2_Monster() const {
     return test_type() == MyGame::Example::Any_MyGame_Example2_Monster ? static_cast<const MyGame::Example2::Monster *>(test()) : nullptr;
   }
+  template<typename T> T *mutable_test_as();
+  MyGame::Example::Monster *mutable_test_as_Monster() {
+    return test_type() == MyGame::Example::Any_Monster ? static_cast<MyGame::Example::Monster *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_test_as_TestSimpleTableWithEnum() {
+    return test_type() == MyGame::Example::Any_TestSimpleTableWithEnum ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_test_as_MyGame_Example2_Monster() {
+    return test_type() == MyGame::Example::Any_MyGame_Example2_Monster ? static_cast<MyGame::Example2::Monster *>(mutable_test()) : nullptr;
+  }
   void *mutable_test() {
     return GetPointer<void *>(VT_TEST);
   }
@@ -1723,6 +1733,16 @@
   const MyGame::Example2::Monster *any_unique_as_M2() const {
     return any_unique_type() == MyGame::Example::AnyUniqueAliases_M2 ? static_cast<const MyGame::Example2::Monster *>(any_unique()) : nullptr;
   }
+  template<typename T> T *mutable_any_unique_as();
+  MyGame::Example::Monster *mutable_any_unique_as_M() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_M ? static_cast<MyGame::Example::Monster *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_any_unique_as_TS() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_TS ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_any_unique_as_M2() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_M2 ? static_cast<MyGame::Example2::Monster *>(mutable_any_unique()) : nullptr;
+  }
   void *mutable_any_unique() {
     return GetPointer<void *>(VT_ANY_UNIQUE);
   }
@@ -1741,6 +1761,15 @@
   const MyGame::Example::Monster *any_ambiguous_as_M3() const {
     return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M3 ? static_cast<const MyGame::Example::Monster *>(any_ambiguous()) : nullptr;
   }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M1() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M1 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M2() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M2 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M3() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M3 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
   void *mutable_any_ambiguous() {
     return GetPointer<void *>(VT_ANY_AMBIGUOUS);
   }
@@ -1950,26 +1979,50 @@
   return test_as_Monster();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_test_as<MyGame::Example::Monster>() {
+  return mutable_test_as_Monster();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::test_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return test_as_TestSimpleTableWithEnum();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_test_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_test_as_TestSimpleTableWithEnum();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::test_as<MyGame::Example2::Monster>() const {
   return test_as_MyGame_Example2_Monster();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_test_as<MyGame::Example2::Monster>() {
+  return mutable_test_as_MyGame_Example2_Monster();
+}
+
 template<> inline const MyGame::Example::Monster *Monster::any_unique_as<MyGame::Example::Monster>() const {
   return any_unique_as_M();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_any_unique_as<MyGame::Example::Monster>() {
+  return mutable_any_unique_as_M();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return any_unique_as_TS();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_any_unique_as_TS();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::any_unique_as<MyGame::Example2::Monster>() const {
   return any_unique_as_M2();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_any_unique_as<MyGame::Example2::Monster>() {
+  return mutable_any_unique_as_M2();
+}
+
 struct MonsterBuilder {
   typedef Monster Table;
   ::flatbuffers::FlatBufferBuilder &fbb_;
diff --git a/tests/monster_test_suffix/monster_test_suffix.hpp b/tests/monster_test_suffix/monster_test_suffix.hpp
index d478d89..91c5e32 100644
--- a/tests/monster_test_suffix/monster_test_suffix.hpp
+++ b/tests/monster_test_suffix/monster_test_suffix.hpp
@@ -1488,6 +1488,16 @@
   const MyGame::Example2::Monster *test_as_MyGame_Example2_Monster() const {
     return test_type() == MyGame::Example::Any_MyGame_Example2_Monster ? static_cast<const MyGame::Example2::Monster *>(test()) : nullptr;
   }
+  template<typename T> T *mutable_test_as();
+  MyGame::Example::Monster *mutable_test_as_Monster() {
+    return test_type() == MyGame::Example::Any_Monster ? static_cast<MyGame::Example::Monster *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_test_as_TestSimpleTableWithEnum() {
+    return test_type() == MyGame::Example::Any_TestSimpleTableWithEnum ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_test()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_test_as_MyGame_Example2_Monster() {
+    return test_type() == MyGame::Example::Any_MyGame_Example2_Monster ? static_cast<MyGame::Example2::Monster *>(mutable_test()) : nullptr;
+  }
   void *mutable_test() {
     return GetPointer<void *>(VT_TEST);
   }
@@ -1723,6 +1733,16 @@
   const MyGame::Example2::Monster *any_unique_as_M2() const {
     return any_unique_type() == MyGame::Example::AnyUniqueAliases_M2 ? static_cast<const MyGame::Example2::Monster *>(any_unique()) : nullptr;
   }
+  template<typename T> T *mutable_any_unique_as();
+  MyGame::Example::Monster *mutable_any_unique_as_M() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_M ? static_cast<MyGame::Example::Monster *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example::TestSimpleTableWithEnum *mutable_any_unique_as_TS() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_TS ? static_cast<MyGame::Example::TestSimpleTableWithEnum *>(mutable_any_unique()) : nullptr;
+  }
+  MyGame::Example2::Monster *mutable_any_unique_as_M2() {
+    return any_unique_type() == MyGame::Example::AnyUniqueAliases_M2 ? static_cast<MyGame::Example2::Monster *>(mutable_any_unique()) : nullptr;
+  }
   void *mutable_any_unique() {
     return GetPointer<void *>(VT_ANY_UNIQUE);
   }
@@ -1741,6 +1761,15 @@
   const MyGame::Example::Monster *any_ambiguous_as_M3() const {
     return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M3 ? static_cast<const MyGame::Example::Monster *>(any_ambiguous()) : nullptr;
   }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M1() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M1 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M2() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M2 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
+  MyGame::Example::Monster *mutable_any_ambiguous_as_M3() {
+    return any_ambiguous_type() == MyGame::Example::AnyAmbiguousAliases_M3 ? static_cast<MyGame::Example::Monster *>(mutable_any_ambiguous()) : nullptr;
+  }
   void *mutable_any_ambiguous() {
     return GetPointer<void *>(VT_ANY_AMBIGUOUS);
   }
@@ -1950,26 +1979,50 @@
   return test_as_Monster();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_test_as<MyGame::Example::Monster>() {
+  return mutable_test_as_Monster();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::test_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return test_as_TestSimpleTableWithEnum();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_test_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_test_as_TestSimpleTableWithEnum();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::test_as<MyGame::Example2::Monster>() const {
   return test_as_MyGame_Example2_Monster();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_test_as<MyGame::Example2::Monster>() {
+  return mutable_test_as_MyGame_Example2_Monster();
+}
+
 template<> inline const MyGame::Example::Monster *Monster::any_unique_as<MyGame::Example::Monster>() const {
   return any_unique_as_M();
 }
 
+template<> inline MyGame::Example::Monster *Monster::mutable_any_unique_as<MyGame::Example::Monster>() {
+  return mutable_any_unique_as_M();
+}
+
 template<> inline const MyGame::Example::TestSimpleTableWithEnum *Monster::any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() const {
   return any_unique_as_TS();
 }
 
+template<> inline MyGame::Example::TestSimpleTableWithEnum *Monster::mutable_any_unique_as<MyGame::Example::TestSimpleTableWithEnum>() {
+  return mutable_any_unique_as_TS();
+}
+
 template<> inline const MyGame::Example2::Monster *Monster::any_unique_as<MyGame::Example2::Monster>() const {
   return any_unique_as_M2();
 }
 
+template<> inline MyGame::Example2::Monster *Monster::mutable_any_unique_as<MyGame::Example2::Monster>() {
+  return mutable_any_unique_as_M2();
+}
+
 struct MonsterBuilder {
   typedef Monster Table;
   ::flatbuffers::FlatBufferBuilder &fbb_;
diff --git a/tests/namespace_test/namespace_test2_generated.h b/tests/namespace_test/namespace_test2_generated.h
index f269807..416c9ff 100644
--- a/tests/namespace_test/namespace_test2_generated.h
+++ b/tests/namespace_test/namespace_test2_generated.h
@@ -117,6 +117,10 @@
   const NamespaceA::NamespaceB::TableInNestedNS *foo_union_as_TableInNestedNS() const {
     return foo_union_type() == NamespaceA::NamespaceB::UnionInNestedNS_TableInNestedNS ? static_cast<const NamespaceA::NamespaceB::TableInNestedNS *>(foo_union()) : nullptr;
   }
+  template<typename T> T *mutable_foo_union_as();
+  NamespaceA::NamespaceB::TableInNestedNS *mutable_foo_union_as_TableInNestedNS() {
+    return foo_union_type() == NamespaceA::NamespaceB::UnionInNestedNS_TableInNestedNS ? static_cast<NamespaceA::NamespaceB::TableInNestedNS *>(mutable_foo_union()) : nullptr;
+  }
   void *mutable_foo_union() {
     return GetPointer<void *>(VT_FOO_UNION);
   }
@@ -147,6 +151,10 @@
   return foo_union_as_TableInNestedNS();
 }
 
+template<> inline NamespaceA::NamespaceB::TableInNestedNS *TableInFirstNS::mutable_foo_union_as<NamespaceA::NamespaceB::TableInNestedNS>() {
+  return mutable_foo_union_as_TableInNestedNS();
+}
+
 struct TableInFirstNSBuilder {
   typedef TableInFirstNS Table;
   ::flatbuffers::FlatBufferBuilder &fbb_;
diff --git a/tests/union_underlying_type_test_generated.h b/tests/union_underlying_type_test_generated.h
index ff62be7..7f7df72 100644
--- a/tests/union_underlying_type_test_generated.h
+++ b/tests/union_underlying_type_test_generated.h
@@ -420,6 +420,16 @@
   const UnionUnderlyingType::C *test_union_as_C() const {
     return test_union_type() == UnionUnderlyingType::ABC::C ? static_cast<const UnionUnderlyingType::C *>(test_union()) : nullptr;
   }
+  template<typename T> T *mutable_test_union_as();
+  UnionUnderlyingType::A *mutable_test_union_as_A() {
+    return test_union_type() == UnionUnderlyingType::ABC::A ? static_cast<UnionUnderlyingType::A *>(mutable_test_union()) : nullptr;
+  }
+  UnionUnderlyingType::B *mutable_test_union_as_B() {
+    return test_union_type() == UnionUnderlyingType::ABC::B ? static_cast<UnionUnderlyingType::B *>(mutable_test_union()) : nullptr;
+  }
+  UnionUnderlyingType::C *mutable_test_union_as_C() {
+    return test_union_type() == UnionUnderlyingType::ABC::C ? static_cast<UnionUnderlyingType::C *>(mutable_test_union()) : nullptr;
+  }
   void *mutable_test_union() {
     return GetPointer<void *>(VT_TEST_UNION);
   }
@@ -457,14 +467,26 @@
   return test_union_as_A();
 }
 
+template<> inline UnionUnderlyingType::A *D::mutable_test_union_as<UnionUnderlyingType::A>() {
+  return mutable_test_union_as_A();
+}
+
 template<> inline const UnionUnderlyingType::B *D::test_union_as<UnionUnderlyingType::B>() const {
   return test_union_as_B();
 }
 
+template<> inline UnionUnderlyingType::B *D::mutable_test_union_as<UnionUnderlyingType::B>() {
+  return mutable_test_union_as_B();
+}
+
 template<> inline const UnionUnderlyingType::C *D::test_union_as<UnionUnderlyingType::C>() const {
   return test_union_as_C();
 }
 
+template<> inline UnionUnderlyingType::C *D::mutable_test_union_as<UnionUnderlyingType::C>() {
+  return mutable_test_union_as_C();
+}
+
 struct DBuilder {
   typedef D Table;
   ::flatbuffers::FlatBufferBuilder &fbb_;
diff --git a/tests/union_vector/union_vector_generated.h b/tests/union_vector/union_vector_generated.h
index 25a0d33..d057304 100644
--- a/tests/union_vector/union_vector_generated.h
+++ b/tests/union_vector/union_vector_generated.h
@@ -623,6 +623,24 @@
   const ::flatbuffers::String *main_character_as_Unused() const {
     return main_character_type() == Character_Unused ? static_cast<const ::flatbuffers::String *>(main_character()) : nullptr;
   }
+  Attacker *mutable_main_character_as_MuLan() {
+    return main_character_type() == Character_MuLan ? static_cast<Attacker *>(mutable_main_character()) : nullptr;
+  }
+  Rapunzel *mutable_main_character_as_Rapunzel() {
+    return main_character_type() == Character_Rapunzel ? static_cast<Rapunzel *>(mutable_main_character()) : nullptr;
+  }
+  BookReader *mutable_main_character_as_Belle() {
+    return main_character_type() == Character_Belle ? static_cast<BookReader *>(mutable_main_character()) : nullptr;
+  }
+  BookReader *mutable_main_character_as_BookFan() {
+    return main_character_type() == Character_BookFan ? static_cast<BookReader *>(mutable_main_character()) : nullptr;
+  }
+  ::flatbuffers::String *mutable_main_character_as_Other() {
+    return main_character_type() == Character_Other ? static_cast<::flatbuffers::String *>(mutable_main_character()) : nullptr;
+  }
+  ::flatbuffers::String *mutable_main_character_as_Unused() {
+    return main_character_type() == Character_Unused ? static_cast<::flatbuffers::String *>(mutable_main_character()) : nullptr;
+  }
   void *mutable_main_character() {
     return GetPointer<void *>(VT_MAIN_CHARACTER);
   }