Allow other pointer types than unique_ptr for object API.

Change-Id: I945890ce667a2f5a6c0495e78fd5326ed33b9914
Tested: on Linux.
Bug: 30135763
diff --git a/docs/source/CppUsage.md b/docs/source/CppUsage.md
index 88b6e45..4a9c78e 100755
--- a/docs/source/CppUsage.md
+++ b/docs/source/CppUsage.md
@@ -99,7 +99,7 @@
 To use:
 
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
-    auto monsterobj = GetMonster(buffer)->UnPack();
+    auto monsterobj = UnpackMonster(buffer);
     cout << monsterobj->name;  // This is now a std::string!
     monsterobj->name = "Bob";  // Change the name.
     FlatBufferBuilder fbb;
@@ -125,6 +125,15 @@
 When you call `UnPack` (or `Create`), you'll need a function that maps from
 hash to the object (see `resolver_function_t` for details).
 
+# Using different pointer types.
+
+By default the object tree is built out of `std::unique_ptr`, but you can
+influence this either globally (using the `--cpp-ptr-type` argument to
+`flatc`) or per field (using the `cpp_ptr_type` attribute) to by any smart
+pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
+pointers. Unlike the smart pointers, naked pointers do not manage memory for
+you, so you'll have to manage their lifecycles manually.
+
 ## Reflection (& Resizing)
 
 There is experimental support for reflection in FlatBuffers, allowing you to
diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h
index 63788b7..2440a19 100644
--- a/include/flatbuffers/idl.h
+++ b/include/flatbuffers/idl.h
@@ -347,6 +347,7 @@
   bool generate_name_strings;
   bool escape_proto_identifiers;
   bool generate_object_based_api;
+  std::string cpp_object_api_pointer_type;
   bool union_value_namespacing;
   bool allow_non_utf8;
 
@@ -370,6 +371,7 @@
       generate_name_strings(false),
       escape_proto_identifiers(false),
       generate_object_based_api(false),
+      cpp_object_api_pointer_type("std::unique_ptr"),
       union_value_namespacing(true),
       allow_non_utf8(false),
       lang(IDLOptions::kJava) {}
@@ -451,6 +453,7 @@
     known_attributes_["streaming"] = true;
     known_attributes_["idempotent"] = true;
     known_attributes_["cpp_type"] = true;
+    known_attributes_["cpp_ptr_type"] = true;
   }
 
   ~Parser() {
diff --git a/include/flatbuffers/reflection_generated.h b/include/flatbuffers/reflection_generated.h
index 3bd1590..e0452c8 100644
--- a/include/flatbuffers/reflection_generated.h
+++ b/include/flatbuffers/reflection_generated.h
@@ -529,17 +529,27 @@
   return CreateSchema(_fbb, objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0, enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0, file_ident ? _fbb.CreateString(file_ident) : 0, file_ext ? _fbb.CreateString(file_ext) : 0, root_table);
 }
 
-inline const reflection::Schema *GetSchema(const void *buf) { return flatbuffers::GetRoot<reflection::Schema>(buf); }
+inline const reflection::Schema *GetSchema(const void *buf) {
+  return flatbuffers::GetRoot<reflection::Schema>(buf);
+}
 
-inline const char *SchemaIdentifier() { return "BFBS"; }
+inline const char *SchemaIdentifier() {
+  return "BFBS";
+}
 
-inline bool SchemaBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, SchemaIdentifier()); }
+inline bool SchemaBufferHasIdentifier(const void *buf) {
+  return flatbuffers::BufferHasIdentifier(buf, SchemaIdentifier());
+}
 
-inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier()); }
+inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) {
+  return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
+}
 
 inline const char *SchemaExtension() { return "bfbs"; }
 
-inline void FinishSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<reflection::Schema> root) { fbb.Finish(root, SchemaIdentifier()); }
+inline void FinishSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<reflection::Schema> root) {
+  fbb.Finish(root, SchemaIdentifier());
+}
 
 }  // namespace reflection
 
diff --git a/samples/monster_generated.h b/samples/monster_generated.h
index 71e8b58..fa12e06 100644
--- a/samples/monster_generated.h
+++ b/samples/monster_generated.h
@@ -150,7 +150,7 @@
            VerifyEquipment(verifier, equipped(), equipped_type()) &&
            verifier.EndTable();
   }
-  std::unique_ptr<MonsterT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
+  MonsterT *UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
 };
 
 struct MonsterBuilder {
@@ -232,7 +232,7 @@
            VerifyField<int16_t>(verifier, VT_DAMAGE) &&
            verifier.EndTable();
   }
-  std::unique_ptr<WeaponT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
+  WeaponT *UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
 };
 
 struct WeaponBuilder {
@@ -265,7 +265,8 @@
 
 inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *rehasher = nullptr);
 
-inline std::unique_ptr<MonsterT> Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+  (void)resolver;
   auto _o = new MonsterT();
   { auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); };
   { auto _e = mana(); _o->mana = _e; };
@@ -273,13 +274,14 @@
   { auto _e = name(); if (_e) _o->name = _e->str(); };
   { auto _e = inventory(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } } };
   { auto _e = color(); _o->color = _e; };
-  { auto _e = weapons(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons.push_back(_e->Get(_i)->UnPack(resolver)); } } };
+  { auto _e = weapons(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons.push_back(std::unique_ptr<WeaponT>(_e->Get(_i)->UnPack(resolver))); } } };
   { auto _e = equipped_type(); _o->equipped.type = _e; };
   { auto _e = equipped(); if (_e) _o->equipped.table = EquipmentUnion::UnPack(_e, equipped_type(), resolver); };
-  return std::unique_ptr<MonsterT>(_o);
+  return _o;
 }
 
 inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher) {
+  (void)rehasher;
   return CreateMonster(_fbb,
     _o->pos ? _o->pos.get() : 0,
     _o->mana,
@@ -292,14 +294,16 @@
     _o->equipped.Pack(_fbb));
 }
 
-inline std::unique_ptr<WeaponT> Weapon::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+inline WeaponT *Weapon::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+  (void)resolver;
   auto _o = new WeaponT();
   { auto _e = name(); if (_e) _o->name = _e->str(); };
   { auto _e = damage(); _o->damage = _e; };
-  return std::unique_ptr<WeaponT>(_o);
+  return _o;
 }
 
 inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *rehasher) {
+  (void)rehasher;
   return CreateWeapon(_fbb,
     _o->name.size() ? _fbb.CreateString(_o->name) : 0,
     _o->damage);
@@ -316,7 +320,7 @@
 inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *union_obj, Equipment type, const flatbuffers::resolver_function_t *resolver) {
   switch (type) {
     case Equipment_NONE: return nullptr;
-    case Equipment_Weapon: return reinterpret_cast<const Weapon *>(union_obj)->UnPack(resolver).release();
+    case Equipment_Weapon: return reinterpret_cast<const Weapon *>(union_obj)->UnPack(resolver);
     default: return nullptr;
   }
 }
@@ -336,13 +340,25 @@
   }
 }
 
-inline const MyGame::Sample::Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot<MyGame::Sample::Monster>(buf); }
+inline const MyGame::Sample::Monster *GetMonster(const void *buf) {
+  return flatbuffers::GetRoot<MyGame::Sample::Monster>(buf);
+}
 
-inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot<Monster>(buf); }
+inline Monster *GetMutableMonster(void *buf) {
+  return flatbuffers::GetMutableRoot<Monster>(buf);
+}
 
-inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Sample::Monster>(nullptr); }
+inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) {
+  return verifier.VerifyBuffer<MyGame::Sample::Monster>(nullptr);
+}
 
-inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Sample::Monster> root) { fbb.Finish(root); }
+inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Sample::Monster> root) {
+  fbb.Finish(root);
+}
+
+inline std::unique_ptr<MonsterT> UnPackMonster(const void *buf, const flatbuffers::resolver_function_t *resolver = nullptr) {
+  return std::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(resolver));
+}
 
 }  // namespace Sample
 }  // namespace MyGame
diff --git a/src/flatc.cpp b/src/flatc.cpp
index bb9f395..5f8340e 100644
--- a/src/flatc.cpp
+++ b/src/flatc.cpp
@@ -126,7 +126,8 @@
       "  --gen-onefile      Generate single output file for C#.\n"
       "  --gen-name-strings Generate type name functions for C++.\n"
       "  --escape-proto-ids Disable appending '_' in namespaces names.\n"
-      "  --gen-object-api   Generate an additional object-based API\n"
+      "  --gen-object-api   Generate an additional object-based API.\n"
+      "  --cpp-ptr-type T   Set object API pointer type (default std::unique_ptr)\n"
       "  --raw-binary       Allow binaries without file_indentifier to be read.\n"
       "                     This may crash flatc given a mismatched schema.\n"
       "  --proto            Input is a .proto, translate to .fbs.\n"
@@ -214,6 +215,9 @@
         opts.generate_name_strings = true;
       } else if(arg == "--gen-object-api") {
         opts.generate_object_based_api = true;
+      } else if (arg == "--cpp-ptr-type") {
+        if (++argi >= argc) Error("missing type following" + arg, true);
+        opts.cpp_object_api_pointer_type = argv[argi];
       } else if(arg == "--gen-all") {
         opts.generate_all = true;
         opts.include_dependence_headers = false;
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index ff32c16..268ba80 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -159,40 +159,40 @@
       // The root datatype accessor:
       code += "inline const " + cpp_qualified_name + " *Get";
       code += name;
-      code += "(const void *buf) { return flatbuffers::GetRoot<";
-      code += cpp_qualified_name + ">(buf); }\n\n";
+      code += "(const void *buf) {\n  return flatbuffers::GetRoot<";
+      code += cpp_qualified_name + ">(buf);\n}\n\n";
       if (parser_.opts.mutable_buffer) {
         code += "inline " + name + " *GetMutable";
         code += name;
-        code += "(void *buf) { return flatbuffers::GetMutableRoot<";
-        code += name + ">(buf); }\n\n";
+        code += "(void *buf) {\n  return flatbuffers::GetMutableRoot<";
+        code += name + ">(buf);\n}\n\n";
       }
 
       if (parser_.file_identifier_.length()) {
         // Return the identifier
         code += "inline const char *" + name;
-        code += "Identifier() { return \"" + parser_.file_identifier_;
-        code += "\"; }\n\n";
+        code += "Identifier() {\n  return \"" + parser_.file_identifier_;
+        code += "\";\n}\n\n";
 
         // Check if a buffer has the identifier.
         code += "inline bool " + name;
-        code += "BufferHasIdentifier(const void *buf) { return flatbuffers::";
+        code += "BufferHasIdentifier(const void *buf) {\n  return flatbuffers::";
         code += "BufferHasIdentifier(buf, ";
-        code += name + "Identifier()); }\n\n";
+        code += name + "Identifier());\n}\n\n";
       }
 
       // The root verifier:
       code += "inline bool Verify";
       code += name;
       code +=
-          "Buffer(flatbuffers::Verifier &verifier) { "
-          "return verifier.VerifyBuffer<";
+          "Buffer(flatbuffers::Verifier &verifier) {\n"
+          "  return verifier.VerifyBuffer<";
       code += cpp_qualified_name + ">(";
       if (parser_.file_identifier_.length())
         code += name + "Identifier()";
       else
         code += "nullptr";
-      code += "); }\n\n";
+      code += ");\n}\n\n";
 
       if (parser_.file_extension_.length()) {
         // Return the extension
@@ -205,10 +205,22 @@
       code += "inline void Finish" + name;
       code +=
           "Buffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<";
-      code += cpp_qualified_name + "> root) { fbb.Finish(root";
+      code += cpp_qualified_name + "> root) {\n  fbb.Finish(root";
       if (parser_.file_identifier_.length())
         code += ", " + name + "Identifier()";
-      code += "); }\n\n";
+      code += ");\n}\n\n";
+
+      if (parser_.opts.generate_object_based_api) {
+        // A convenient root unpack function.
+        auto native_name =
+            NativeName(WrapInNameSpace(*parser_.root_struct_def_));
+        code += "inline " + GenTypeNativePtr(native_name, nullptr, false);
+        code += " UnPack" + name;
+        code += "(const void *buf, const flatbuffers::resolver_function_t *";
+        code += "resolver = nullptr) {\n  return ";
+        code += GenTypeNativePtr(native_name, nullptr, true);
+        code += "(Get" + name + "(buf)->UnPack(resolver));\n}\n\n";
+      }
     }
 
     assert(cur_name_space_);
@@ -293,23 +305,42 @@
   // TODO(wvo): make this configurable.
   std::string NativeName(const std::string &name) { return name + "T"; }
 
-  std::string GenTypeNative(const Type &type, bool invector) {
+  const std::string &PtrType(const FieldDef *field) {
+    auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr;
+    return attr ? attr->constant : parser_.opts.cpp_object_api_pointer_type;
+  }
+
+  std::string GenTypeNativePtr(const std::string &type, const FieldDef *field,
+                               bool is_constructor) {
+    auto &ptr_type = PtrType(field);
+    if (ptr_type == "naked") return is_constructor ? "" : type + " *";
+    return ptr_type + "<" + type + ">";
+  }
+
+  std::string GenPtrGet(const FieldDef &field) {
+    auto &ptr_type = PtrType(&field);
+    return ptr_type == "naked" ? "" : ".get()";
+  }
+
+  std::string GenTypeNative(const Type &type, bool invector,
+                            const FieldDef &field) {
     switch (type.base_type) {
       case BASE_TYPE_STRING:
         return "std::string";
       case BASE_TYPE_VECTOR:
-        return "std::vector<" + GenTypeNative(type.VectorType(), true) + ">";
+        return "std::vector<" + GenTypeNative(type.VectorType(), true, field) +
+               ">";
       case BASE_TYPE_STRUCT:
         if (IsStruct(type)) {
           if (invector) {
             return WrapInNameSpace(*type.struct_def);
           } else {
-            return "std::unique_ptr<" +
-                   WrapInNameSpace(*type.struct_def) + ">";
+            return GenTypeNativePtr(WrapInNameSpace(*type.struct_def), &field,
+                                    false);
           }
         } else {
-          return "std::unique_ptr<" +
-                 NativeName(WrapInNameSpace(*type.struct_def)) + ">";
+          return GenTypeNativePtr(NativeName(WrapInNameSpace(*type.struct_def)),
+                                  &field, false);
         }
       case BASE_TYPE_UNION:
         return type.enum_def->name + "Union";
@@ -383,7 +414,7 @@
   }
 
   std::string TableUnPackSignature(StructDef &struct_def, bool inclass) {
-    return "std::unique_ptr<" + NativeName(struct_def.name) + "> " +
+    return NativeName(struct_def.name) + " *" +
            (inclass ? "" : struct_def.name + "::") +
            "UnPack(const flatbuffers::resolver_function_t *resolver" +
            (inclass ? " = nullptr" : "") + ") const";
@@ -490,7 +521,7 @@
       }
       code += "]; }\n\n";
     }
-    
+
     // Generate type traits for unions to map from a type to union enum value.
     if (enum_def.is_union) {
       for (auto it = enum_def.vals.vec.begin();
@@ -507,7 +538,7 @@
         code += "};\n\n";
       }
     }
-    
+
     if (enum_def.is_union) {
       code += UnionVerifySignature(enum_def) + ";\n\n";
     }
@@ -548,7 +579,7 @@
         } else {
           code += ": return reinterpret_cast<const ";
           code += WrapInNameSpace(*ev.struct_def);
-          code += " *>(union_obj)->UnPack(resolver).release();\n";
+          code += " *>(union_obj)->UnPack(resolver);\n";
         }
       }
       code += "    default: return nullptr;\n  }\n}\n\n";
@@ -662,7 +693,7 @@
         auto &field = **it;
         if (!field.deprecated &&  // Deprecated fields won't be accessible.
             field.value.type.base_type != BASE_TYPE_UTYPE) {
-          auto type = GenTypeNative(field.value.type, false);
+          auto type = GenTypeNative(field.value.type, false, field);
           auto cpp_type = field.attributes.Lookup("cpp_type");
           code += "  " + (cpp_type ? cpp_type->constant + " *" : type+ " ") +
                   field.name + ";\n";
@@ -982,6 +1013,7 @@
     if (parser_.opts.generate_object_based_api) {
       // Generate the UnPack() method.
       code += "inline " + TableUnPackSignature(struct_def, false) + " {\n";
+      code += "  (void)resolver;\n";
       code += "  auto _o = new " + NativeName(struct_def.name) + "();\n";
       for (auto it = struct_def.fields.vec.begin();
            it != struct_def.fields.vec.end(); ++it) {
@@ -993,7 +1025,8 @@
           auto dest = deref + field.name;
           auto assign = prefix + dest + " = ";
           auto gen_unpack_val = [&](const Type &type, const std::string &val,
-                                    bool invector) -> std::string {
+                                    bool invector, const FieldDef &afield)
+                                        -> std::string {
             switch (type.base_type) {
               case BASE_TYPE_STRING:
                 return val + "->str()";
@@ -1002,13 +1035,15 @@
                   if (invector) {
                     return "*" + val;
                   } else {
-                    return "std::unique_ptr<" +
-                           WrapInNameSpace (*type.struct_def) +
-                           ">(new " +
-                           WrapInNameSpace (*type.struct_def) + "(*" + val + "))";
+                    return GenTypeNativePtr(WrapInNameSpace(*type.struct_def),
+                                            &afield, true) +
+                           "(new " +
+                           WrapInNameSpace(*type.struct_def) + "(*" + val + "))";
                   }
                 } else {
-                  return val + "->UnPack(resolver)";
+                  return GenTypeNativePtr(NativeName(WrapInNameSpace(
+                             *type.struct_def)), &afield, true) +
+                         "(" + val + "->UnPack(resolver))";
                 }
               default:
                 return val;
@@ -1025,7 +1060,7 @@
               if (field.value.type.element == BASE_TYPE_BOOL)
                 indexing += "!=0";
               code += gen_unpack_val(field.value.type.VectorType(),
-                                     indexing, true);
+                                     indexing, true, field);
               code += "); } }";
               break;
             }
@@ -1052,7 +1087,7 @@
                 code += dest + " = nullptr";
               } else {
                 code += assign;
-                code += gen_unpack_val(field.value.type, "_e", false);
+                code += gen_unpack_val(field.value.type, "_e", false, field);
               }
               code += ";";
               break;
@@ -1061,11 +1096,11 @@
           code += " };\n";
         }
       }
-      code += "  return std::unique_ptr<" + NativeName(struct_def.name);
-      code += ">(_o);\n}\n\n";
+      code += "  return _o;\n}\n\n";
 
       // Generate a CreateX method that works with an unpacked C++ object.
       code += TableCreateSignature(struct_def, false) + " {\n";
+      code += "  (void)rehasher;\n";
       auto before_return_statement = code.size();
       code += "  return Create";
       code += struct_def.name + "(_fbb";
@@ -1116,7 +1151,7 @@
                     code += vector_type.struct_def->name + ">>(" + accessor;
                     code += ".size(), [&](size_t i) { return Create";
                     code += vector_type.struct_def->name + "(_fbb, " + accessor;
-                    code += "[i].get(), rehasher); })";
+                    code += "[i]" + GenPtrGet(field) + ", rehasher); })";
                   }
                   break;
                 default:
@@ -1131,11 +1166,12 @@
               break;
             case BASE_TYPE_STRUCT:
               if (IsStruct(field.value.type)) {
-                code += ptrprefix + accessor + ".get()" + postfix;
+                code += ptrprefix + accessor + GenPtrGet(field) + postfix;
               } else {
                 code += ptrprefix + "Create";
                 code += field.value.type.struct_def->name;
-                code += "(_fbb, " + accessor + ".get(), rehasher)" + postfix;
+                code += "(_fbb, " + accessor + GenPtrGet(field) + ", rehasher)";
+                code += postfix;
               }
               break;
             default:
diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h
index e4ea3f6..6e8831e 100644
--- a/tests/monster_test_generated.h
+++ b/tests/monster_test_generated.h
@@ -158,7 +158,7 @@
     return VerifyTableStart(verifier) &&
            verifier.EndTable();
   }
-  std::unique_ptr<MonsterT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
+  MonsterT *UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
 };
 
 struct MonsterBuilder {
@@ -198,7 +198,7 @@
            VerifyField<int8_t>(verifier, VT_COLOR) &&
            verifier.EndTable();
   }
-  std::unique_ptr<TestSimpleTableWithEnumT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
+  TestSimpleTableWithEnumT *UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
 };
 
 struct TestSimpleTableWithEnumBuilder {
@@ -248,7 +248,7 @@
            VerifyField<uint16_t>(verifier, VT_COUNT) &&
            verifier.EndTable();
   }
-  std::unique_ptr<StatT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
+  StatT *UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
 };
 
 struct StatBuilder {
@@ -454,7 +454,7 @@
            verifier.VerifyVectorOfStrings(testarrayofstring2()) &&
            verifier.EndTable();
   }
-  std::unique_ptr<MonsterT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
+  MonsterT *UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
 };
 
 struct MonsterBuilder {
@@ -596,12 +596,14 @@
 
 namespace Example2 {
 
-inline std::unique_ptr<MonsterT> Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+  (void)resolver;
   auto _o = new MonsterT();
-  return std::unique_ptr<MonsterT>(_o);
+  return _o;
 }
 
 inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher) {
+  (void)rehasher;
   (void)_o;
   return CreateMonster(_fbb);
 }
@@ -610,33 +612,38 @@
 
 namespace Example {
 
-inline std::unique_ptr<TestSimpleTableWithEnumT> TestSimpleTableWithEnum::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+inline TestSimpleTableWithEnumT *TestSimpleTableWithEnum::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+  (void)resolver;
   auto _o = new TestSimpleTableWithEnumT();
   { auto _e = color(); _o->color = _e; };
-  return std::unique_ptr<TestSimpleTableWithEnumT>(_o);
+  return _o;
 }
 
 inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o, const flatbuffers::rehasher_function_t *rehasher) {
+  (void)rehasher;
   return CreateTestSimpleTableWithEnum(_fbb,
     _o->color);
 }
 
-inline std::unique_ptr<StatT> Stat::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+inline StatT *Stat::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+  (void)resolver;
   auto _o = new StatT();
   { auto _e = id(); if (_e) _o->id = _e->str(); };
   { auto _e = val(); _o->val = _e; };
   { auto _e = count(); _o->count = _e; };
-  return std::unique_ptr<StatT>(_o);
+  return _o;
 }
 
 inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const StatT *_o, const flatbuffers::rehasher_function_t *rehasher) {
+  (void)rehasher;
   return CreateStat(_fbb,
     _o->id.size() ? _fbb.CreateString(_o->id) : 0,
     _o->val,
     _o->count);
 }
 
-inline std::unique_ptr<MonsterT> Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
+  (void)resolver;
   auto _o = new MonsterT();
   { auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); };
   { auto _e = mana(); _o->mana = _e; };
@@ -648,10 +655,10 @@
   { auto _e = test(); if (_e) _o->test.table = AnyUnion::UnPack(_e, test_type(), resolver); };
   { auto _e = test4(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test4.push_back(*_e->Get(_i)); } } };
   { auto _e = testarrayofstring(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring.push_back(_e->Get(_i)->str()); } } };
-  { auto _e = testarrayoftables(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables.push_back(_e->Get(_i)->UnPack(resolver)); } } };
-  { auto _e = enemy(); if (_e) _o->enemy = _e->UnPack(resolver); };
+  { auto _e = testarrayoftables(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables.push_back(std::unique_ptr<MonsterT>(_e->Get(_i)->UnPack(resolver))); } } };
+  { auto _e = enemy(); if (_e) _o->enemy = std::unique_ptr<MonsterT>(_e->UnPack(resolver)); };
   { auto _e = testnestedflatbuffer(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testnestedflatbuffer.push_back(_e->Get(_i)); } } };
-  { auto _e = testempty(); if (_e) _o->testempty = _e->UnPack(resolver); };
+  { auto _e = testempty(); if (_e) _o->testempty = std::unique_ptr<StatT>(_e->UnPack(resolver)); };
   { auto _e = testbool(); _o->testbool = _e; };
   { auto _e = testhashs32_fnv1(); _o->testhashs32_fnv1 = _e; };
   { auto _e = testhashu32_fnv1(); _o->testhashu32_fnv1 = _e; };
@@ -666,10 +673,11 @@
   { auto _e = testf2(); _o->testf2 = _e; };
   { auto _e = testf3(); _o->testf3 = _e; };
   { auto _e = testarrayofstring2(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring2.push_back(_e->Get(_i)->str()); } } };
-  return std::unique_ptr<MonsterT>(_o);
+  return _o;
 }
 
 inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher) {
+  (void)rehasher;
   return CreateMonster(_fbb,
     _o->pos ? _o->pos.get() : 0,
     _o->mana,
@@ -714,9 +722,9 @@
 inline flatbuffers::NativeTable *AnyUnion::UnPack(const void *union_obj, Any type, const flatbuffers::resolver_function_t *resolver) {
   switch (type) {
     case Any_NONE: return nullptr;
-    case Any_Monster: return reinterpret_cast<const Monster *>(union_obj)->UnPack(resolver).release();
-    case Any_TestSimpleTableWithEnum: return reinterpret_cast<const TestSimpleTableWithEnum *>(union_obj)->UnPack(resolver).release();
-    case Any_MyGame_Example2_Monster: return reinterpret_cast<const MyGame::Example2::Monster *>(union_obj)->UnPack(resolver).release();
+    case Any_Monster: return reinterpret_cast<const Monster *>(union_obj)->UnPack(resolver);
+    case Any_TestSimpleTableWithEnum: return reinterpret_cast<const TestSimpleTableWithEnum *>(union_obj)->UnPack(resolver);
+    case Any_MyGame_Example2_Monster: return reinterpret_cast<const MyGame::Example2::Monster *>(union_obj)->UnPack(resolver);
     default: return nullptr;
   }
 }
@@ -740,19 +748,35 @@
   }
 }
 
-inline const MyGame::Example::Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot<MyGame::Example::Monster>(buf); }
+inline const MyGame::Example::Monster *GetMonster(const void *buf) {
+  return flatbuffers::GetRoot<MyGame::Example::Monster>(buf);
+}
 
-inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot<Monster>(buf); }
+inline Monster *GetMutableMonster(void *buf) {
+  return flatbuffers::GetMutableRoot<Monster>(buf);
+}
 
-inline const char *MonsterIdentifier() { return "MONS"; }
+inline const char *MonsterIdentifier() {
+  return "MONS";
+}
 
-inline bool MonsterBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, MonsterIdentifier()); }
+inline bool MonsterBufferHasIdentifier(const void *buf) {
+  return flatbuffers::BufferHasIdentifier(buf, MonsterIdentifier());
+}
 
-inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Example::Monster>(MonsterIdentifier()); }
+inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) {
+  return verifier.VerifyBuffer<MyGame::Example::Monster>(MonsterIdentifier());
+}
 
 inline const char *MonsterExtension() { return "mon"; }
 
-inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Example::Monster> root) { fbb.Finish(root, MonsterIdentifier()); }
+inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Example::Monster> root) {
+  fbb.Finish(root, MonsterIdentifier());
+}
+
+inline std::unique_ptr<MonsterT> UnPackMonster(const void *buf, const flatbuffers::resolver_function_t *resolver = nullptr) {
+  return std::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(resolver));
+}
 
 }  // namespace Example
 }  // namespace MyGame
diff --git a/tests/test.cpp b/tests/test.cpp
index d6c709b..f2854c6 100644
--- a/tests/test.cpp
+++ b/tests/test.cpp
@@ -326,7 +326,7 @@
   });
 
   // Turn a buffer into C++ objects.
-  auto monster1 = GetMonster(flatbuf)->UnPack(&resolver);
+  auto monster1 = UnPackMonster(flatbuf, &resolver);
 
   // Re-serialize the data.
   flatbuffers::FlatBufferBuilder fbb1;
@@ -334,7 +334,7 @@
               MonsterIdentifier());
 
   // Unpack again, and re-serialize again.
-  auto monster2 = GetMonster(fbb1.GetBufferPointer())->UnPack(&resolver);
+  auto monster2 = UnPackMonster(fbb1.GetBufferPointer(), &resolver);
   flatbuffers::FlatBufferBuilder fbb2;
   fbb2.Finish(CreateMonster(fbb2, monster2.get(), &rehasher),
               MonsterIdentifier());