Merge branch 'master' of https://github.com/google/flatbuffers
diff --git a/docs/source/Schemas.md b/docs/source/Schemas.md
index f9fe486..d5cb441 100755
--- a/docs/source/Schemas.md
+++ b/docs/source/Schemas.md
@@ -285,9 +285,6 @@
     code may access it directly, without checking for NULL. If the constructing
     code does not initialize this field, they will get an assert, and also
     the verifier will fail on buffers that have missing required fields.
--   `original_order` (on a table): since elements in a table do not need
-    to be stored in any particular order, they are often optimized for
-    space by sorting them to size. This attribute stops that from happening.
 -   `force_align: size` (on a struct): force the alignment of this struct
     to be something higher than what it is naturally aligned to. Causes
     these structs to be aligned to that amount inside a buffer, IF that
@@ -308,6 +305,10 @@
     value during JSON parsing is allowed to be a string, which will then be
     stored as its hash. The value of attribute is the hashing algorithm to
     use, one of `fnv1_32` `fnv1_64` `fnv1a_32` `fnv1a_64`.
+-   `original_order` (on a table): since elements in a table do not need
+    to be stored in any particular order, they are often optimized for
+    space by sorting them to size. This attribute stops that from happening.
+    There should generally not be any reason to use this flag.
 
 ## JSON Parsing
 
@@ -363,6 +364,66 @@
 It also generates these escape codes back again when generating JSON from a
 binary representation.
 
+## Guidelines
+
+### Efficiency
+
+FlatBuffers is all about efficiency, but to realize that efficiency you
+require an efficient schema. There are usually multiple choices on
+how to represent data that have vastly different size characteristics.
+
+It is very common nowadays to represent any kind of data as dictionaries
+(as in e.g. JSON), because of its flexibility and extensibility. While
+it is possible to emulate this in FlatBuffers (as a vector
+of tables with key and value(s)), this is a bad match for a strongly
+typed system like FlatBuffers, leading to relatively large binaries.
+FlatBuffer tables are more flexible than classes/structs in most systems,
+since having a large number of fields only few of which are actually
+used is still efficient. You should thus try to organize your data
+as much as possible such that you can use tables where you might be
+tempted to use a dictionary.
+
+Similarly, strings as values should only be used when they are
+truely open-ended. If you can, always use an enum instead.
+
+FlatBuffers doesn't have inheritance, so the way to represent a set
+of related data structures is a union. Unions do have a cost however,
+so an alternative to a union is to have a single table that has
+all the fields of all the data structures you are trying to
+represent, if they are relatively similar / share many fields.
+Again, this is efficient because optional fields are cheap.
+
+FlatBuffers supports the full range of integer sizes, so try to pick
+the smallest size needed, rather than defaulting to int/long.
+
+Remember that you can share data (refer to the same string/table
+within a buffer), so factoring out repeating data into its own
+data structure may be worth it.
+
+### Style guide
+
+Identifiers in a schema are meant to translate to many different programming
+languages, so using the style of your "main" language is generally a bad idea.
+
+For this reason, below is a suggested style guide to adhere to, to keep schemas
+consistent for interoperation regardless of the target language.
+
+Where possible, the code generators for specific languages will generate
+identifiers that adhere to the language style, based on the schema identifiers.
+
+- Table, struct, enum and rpc names (types): UpperCamelCase.
+- Table and struct field names: snake_case. This is translated to lowerCamelCase
+  automatically for some languages, e.g. Java.
+- Enum values: UpperCamelCase.
+- namespaces: UpperCamelCase.
+
+Formatting (this is less important, but still worth adhering to):
+
+- Opening brace: on the same line as the start of the declaration.
+- Spacing: Indent by 2 spaces. None around `:` for types, on both sides for `=`.
+
+For an example, see the schema at the top of this file.
+
 ## Gotchas
 
 ### Schemas and version control
diff --git a/samples/monster_generated.h b/samples/monster_generated.h
index 1833c62..ded7846 100644
--- a/samples/monster_generated.h
+++ b/samples/monster_generated.h
@@ -38,21 +38,6 @@
   Equipment_MAX = Equipment_Weapon
 };
 
-struct EquipmentUnion {
-  Equipment type;
-
-  flatbuffers::NativeTable *table;
-  EquipmentUnion() : type(Equipment_NONE), table(nullptr) {}
-  EquipmentUnion(const EquipmentUnion &);
-  EquipmentUnion &operator=(const EquipmentUnion &);
-  ~EquipmentUnion();
-
-  static flatbuffers::NativeTable *UnPack(const void *union_obj, Equipment type, const flatbuffers::resolver_function_t *resolver);
-  flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher = nullptr) const;
-
-  WeaponT *AsWeapon() { return type == Equipment_Weapon ? reinterpret_cast<WeaponT *>(table) : nullptr; }
-};
-
 inline const char **EnumNamesEquipment() {
   static const char *names[] = { "NONE", "Weapon", nullptr };
   return names;
@@ -68,6 +53,31 @@
   static const Equipment enum_value = Equipment_Weapon;
 };
 
+struct EquipmentUnion {
+  Equipment type = Equipment_NONE;
+
+  flatbuffers::NativeTable *table = nullptr;
+  EquipmentUnion() : type(Equipment_NONE), table(nullptr) {}
+  EquipmentUnion(const EquipmentUnion &);
+  EquipmentUnion &operator=(const EquipmentUnion &);
+  ~EquipmentUnion() { Reset(); }
+  void Reset();
+
+  template <typename T>
+  void Set(T&& value) {
+    Reset();
+    type = EquipmentTraits<typename T::TableType>::enum_value;
+    if (type != Equipment_NONE) {
+      table = new T(std::move(value));
+    }
+  }
+
+  static flatbuffers::NativeTable *UnPack(const void *union_obj, Equipment type, const flatbuffers::resolver_function_t *resolver);
+  flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher = nullptr) const;
+
+  WeaponT *AsWeapon() { return type == Equipment_Weapon ? reinterpret_cast<WeaponT *>(table) : nullptr; }
+};
+
 inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_obj, Equipment type);
 
 MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
@@ -101,6 +111,10 @@
   Color color;
   std::vector<std::unique_ptr<WeaponT>> weapons;
   EquipmentUnion equipped;
+  MonsterT()
+    : mana(150),
+      hp(100),
+      color(Color_Blue) {}
 };
 
 struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -218,6 +232,8 @@
   typedef Weapon TableType;
   std::string name;
   int16_t damage;
+  WeaponT()
+    : damage(0) {}
 };
 
 struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -347,11 +363,13 @@
   }
 }
 
-inline EquipmentUnion::~EquipmentUnion() {
+inline void EquipmentUnion::Reset() {
   switch (type) {
     case Equipment_Weapon: delete reinterpret_cast<WeaponT *>(table); break;
-    default:;
+    default: break;
   }
+  table = nullptr;
+  type = Equipment_NONE;
 }
 
 inline const MyGame::Sample::Monster *GetMonster(const void *buf) {
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index 8681e17..0436f4d 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -472,36 +472,6 @@
               GenTypeBasic(enum_def.underlying_type, false) + ")\n";
     code += "\n";
 
-    if (parser_.opts.generate_object_based_api && enum_def.is_union) {
-      // Generate a union type
-      code += "struct " + enum_def.name + "Union {\n";
-      code += "  " + enum_def.name + " type;\n\n";
-      code += "  flatbuffers::NativeTable *table;\n";
-      code += "  " + enum_def.name + "Union() : type(";
-      code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
-      code += "), table(nullptr) {}\n";
-      code += "  " + enum_def.name + "Union(const ";
-      code += enum_def.name + "Union &);\n";
-      code += "  " + enum_def.name + "Union &operator=(const ";
-      code += enum_def.name + "Union &);\n";
-      code += "  ~" + enum_def.name + "Union();\n\n";
-      code += "  " + UnionUnPackSignature(enum_def, true) + ";\n";
-      code += "  " + UnionPackSignature(enum_def, true) + ";\n\n";
-      for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
-           ++it) {
-        auto &ev = **it;
-        if (ev.value) {
-          auto native_name = NativeName(WrapInNameSpace(*ev.struct_def));
-          code += "  " + native_name + " *As";
-          code += ev.name + "() { return type == ";
-          code += GetEnumValUse(enum_def, ev, parser_.opts);
-          code += " ? reinterpret_cast<" + native_name;
-          code += " *>(table) : nullptr; }\n";
-        }
-      }
-      code += "};\n\n";
-    }
-
     // Generate a generate string table for enum values.
     // Problem is, if values are very sparse that could generate really big
     // tables. Ideally in that case we generate a map lookup instead, but for
@@ -552,6 +522,50 @@
       }
     }
 
+    if (parser_.opts.generate_object_based_api && enum_def.is_union) {
+      // Generate a union type
+      code += "struct " + enum_def.name + "Union {\n";
+      code += "  " + enum_def.name + " type = ";
+      code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
+      code += ";\n\n";
+      code += "  flatbuffers::NativeTable *table = nullptr;\n";
+      code += "  " + enum_def.name + "Union() : type(";
+      code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
+      code += "), table(nullptr) {}\n";
+      code += "  " + enum_def.name + "Union(const ";
+      code += enum_def.name + "Union &);\n";
+      code += "  " + enum_def.name + "Union &operator=(const ";
+      code += enum_def.name + "Union &);\n";
+      code += "  ~" + enum_def.name + "Union() { Reset(); }\n";
+      code += "  void Reset();\n\n";
+      code += "  template <typename T>\n";
+      code += "  void Set(T&& value) {\n";
+      code += "    Reset();\n";
+      code += "    type = " + enum_def.name;
+      code += "Traits<typename T::TableType>::enum_value;\n";
+      code += "    if (type != ";
+      code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
+      code += ") {\n";
+      code += "      table = new T(std::forward<T>(value));\n";
+      code += "    }\n";
+      code += "  }\n\n";
+      code += "  " + UnionUnPackSignature(enum_def, true) + ";\n";
+      code += "  " + UnionPackSignature(enum_def, true) + ";\n\n";
+      for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
+           ++it) {
+        auto &ev = **it;
+        if (ev.value) {
+          auto native_name = NativeName(WrapInNameSpace(*ev.struct_def));
+          code += "  " + native_name + " *As";
+          code += ev.name + "() { return type == ";
+          code += GetEnumValUse(enum_def, ev, parser_.opts);
+          code += " ? reinterpret_cast<" + native_name;
+          code += " *>(table) : nullptr; }\n";
+        }
+      }
+      code += "};\n\n";
+    }
+
     if (enum_def.is_union) {
       code += UnionVerifySignature(enum_def) + ";\n\n";
     }
@@ -614,8 +628,7 @@
       code += "    default: return 0;\n  }\n}\n\n";
 
       // Generate a union destructor.
-      code += "inline " + enum_def.name + "Union::~";
-      code += enum_def.name + "Union() {\n";
+      code += "inline void " + enum_def.name + "Union::Reset() {\n";
       code += "  switch (type) {\n";
       for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
            ++it) {
@@ -627,7 +640,13 @@
           code += " *>(table); break;\n";
         }
       }
-      code += "    default:;\n  }\n}\n\n";
+      code += "    default: break;\n";
+      code += "  }\n";
+      code += "  table = nullptr;\n";
+      code += "  type = ";
+      code += GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"), parser_.opts);
+      code += ";\n";
+      code += "}\n\n";
     }
   }
 
@@ -672,26 +691,72 @@
                : field.value.constant;
   }
 
-  void GenSimpleParam(std::string &code, FieldDef &field) {
-    code += ",\n    " + GenTypeWire(field.value.type, " ", true);
-    code += field.name + " = ";
+  std::string GetDefaultScalarValue(const FieldDef &field) {
     if (field.value.type.enum_def && IsScalar(field.value.type.base_type)) {
       auto ev = field.value.type.enum_def->ReverseLookup(
           static_cast<int>(StringToInt(field.value.constant.c_str())), false);
       if (ev) {
-        code += WrapInNameSpace(
+        return WrapInNameSpace(
             field.value.type.enum_def->defined_namespace,
             GetEnumValUse(*field.value.type.enum_def, *ev, parser_.opts));
       } else {
-        code += GenUnderlyingCast(field, true, field.value.constant);
+        return GenUnderlyingCast(field, true, field.value.constant);
       }
     } else if (field.value.type.base_type == BASE_TYPE_BOOL) {
-      code += field.value.constant == "0" ? "false" : "true";
+      return field.value.constant == "0" ? "false" : "true";
     } else {
-      code += GenDefaultConstant(field);
+      return GenDefaultConstant(field);
     }
   }
 
+  void GenSimpleParam(std::string &code, FieldDef &field) {
+    code += ",\n    " + GenTypeWire(field.value.type, " ", true);
+    code += field.name + " = " + GetDefaultScalarValue(field);
+  }
+
+  // Generate a member, including a default value for scalars and raw pointers.
+  void GenMember(std::string& code, const FieldDef &field) {
+    if (!field.deprecated &&  // Deprecated fields won't be accessible.
+        field.value.type.base_type != BASE_TYPE_UTYPE) {
+      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";
+    }
+  }
+
+  // Generate the default constructor for this struct. Properly initialize all
+  // scalar members with default values.
+  void GenDefaultConstructor(std::string& code, const StructDef& struct_def) {
+    code += "  " + NativeName(struct_def.name) + "()";
+    std::string initializer_list;
+    for (auto it = struct_def.fields.vec.begin();
+         it != struct_def.fields.vec.end(); ++it) {
+      auto &field = **it;
+      if (!field.deprecated &&  // Deprecated fields won't be accessible.
+          field.value.type.base_type != BASE_TYPE_UTYPE) {
+        auto cpp_type = field.attributes.Lookup("cpp_type");
+        // Scalar types get parsed defaults, raw pointers get nullptrs.
+        if (IsScalar(field.value.type.base_type)) {
+          if (!initializer_list.empty()) {
+            initializer_list += ",\n      ";
+          }
+          initializer_list += field.name + "(" +GetDefaultScalarValue(field) +
+              ")";
+        } else if (cpp_type) {
+          if (!initializer_list.empty()) {
+            code += ",\n      ";
+          }
+          initializer_list += field.name + "(0)";
+        }
+      }
+    }
+    if (!initializer_list.empty()) {
+      code += "\n    : " + initializer_list;
+    }
+    code += " {}\n";
+  }
+
   // Generate an accessor struct, builder structs & function for a table.
   void GenTable(StructDef &struct_def, std::string *code_ptr) {
     std::string &code = *code_ptr;
@@ -707,14 +772,9 @@
       for (auto it = struct_def.fields.vec.begin();
            it != struct_def.fields.vec.end(); ++it) {
         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, field);
-          auto cpp_type = field.attributes.Lookup("cpp_type");
-          code += "  " + (cpp_type ? cpp_type->constant + " *" : type+ " ") +
-                  field.name + ";\n";
-        }
+        GenMember(code, field);
       }
+      GenDefaultConstructor(code, struct_def);
       code += "};\n\n";
     }
 
diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h
index f1be4ac..5714f58 100644
--- a/tests/monster_test_generated.h
+++ b/tests/monster_test_generated.h
@@ -52,23 +52,6 @@
   Any_MAX = Any_MyGame_Example2_Monster
 };
 
-struct AnyUnion {
-  Any type;
-
-  flatbuffers::NativeTable *table;
-  AnyUnion() : type(Any_NONE), table(nullptr) {}
-  AnyUnion(const AnyUnion &);
-  AnyUnion &operator=(const AnyUnion &);
-  ~AnyUnion();
-
-  static flatbuffers::NativeTable *UnPack(const void *union_obj, Any type, const flatbuffers::resolver_function_t *resolver);
-  flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher = nullptr) const;
-
-  MonsterT *AsMonster() { return type == Any_Monster ? reinterpret_cast<MonsterT *>(table) : nullptr; }
-  TestSimpleTableWithEnumT *AsTestSimpleTableWithEnum() { return type == Any_TestSimpleTableWithEnum ? reinterpret_cast<TestSimpleTableWithEnumT *>(table) : nullptr; }
-  MyGame::Example2::MonsterT *AsMyGame_Example2_Monster() { return type == Any_MyGame_Example2_Monster ? reinterpret_cast<MyGame::Example2::MonsterT *>(table) : nullptr; }
-};
-
 inline const char **EnumNamesAny() {
   static const char *names[] = { "NONE", "Monster", "TestSimpleTableWithEnum", "MyGame_Example2_Monster", nullptr };
   return names;
@@ -92,6 +75,33 @@
   static const Any enum_value = Any_MyGame_Example2_Monster;
 };
 
+struct AnyUnion {
+  Any type = Any_NONE;
+
+  flatbuffers::NativeTable *table = nullptr;
+  AnyUnion() : type(Any_NONE), table(nullptr) {}
+  AnyUnion(const AnyUnion &);
+  AnyUnion &operator=(const AnyUnion &);
+  ~AnyUnion() { Reset(); }
+  void Reset();
+
+  template <typename T>
+  void Set(T&& value) {
+    Reset();
+    type = AnyTraits<typename T::TableType>::enum_value;
+    if (type != Any_NONE) {
+      table = new T(std::move(value));
+    }
+  }
+
+  static flatbuffers::NativeTable *UnPack(const void *union_obj, Any type, const flatbuffers::resolver_function_t *resolver);
+  flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher = nullptr) const;
+
+  MonsterT *AsMonster() { return type == Any_Monster ? reinterpret_cast<MonsterT *>(table) : nullptr; }
+  TestSimpleTableWithEnumT *AsTestSimpleTableWithEnum() { return type == Any_TestSimpleTableWithEnum ? reinterpret_cast<TestSimpleTableWithEnumT *>(table) : nullptr; }
+  MyGame::Example2::MonsterT *AsMyGame_Example2_Monster() { return type == Any_MyGame_Example2_Monster ? reinterpret_cast<MyGame::Example2::MonsterT *>(table) : nullptr; }
+};
+
 inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *union_obj, Any type);
 
 MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS {
@@ -152,6 +162,7 @@
 
 struct MonsterT : public flatbuffers::NativeTable {
   typedef Monster TableType;
+  MonsterT() {}
 };
 
 struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -189,6 +200,8 @@
 struct TestSimpleTableWithEnumT : public flatbuffers::NativeTable {
   typedef TestSimpleTableWithEnum TableType;
   Color color;
+  TestSimpleTableWithEnumT()
+    : color(Color_Green) {}
 };
 
 struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -233,6 +246,9 @@
   std::string id;
   int64_t val;
   uint16_t count;
+  StatT()
+    : val(0),
+      count(0) {}
 };
 
 struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -323,6 +339,22 @@
   float testf2;
   float testf3;
   std::vector<std::string> testarrayofstring2;
+  MonsterT()
+    : mana(150),
+      hp(100),
+      color(Color_Blue),
+      testbool(false),
+      testhashs32_fnv1(0),
+      testhashu32_fnv1(0),
+      testhashs64_fnv1(0),
+      testhashu64_fnv1(0),
+      testhashs32_fnv1a(0),
+      testhashu32_fnv1a(0),
+      testhashs64_fnv1a(0),
+      testhashu64_fnv1a(0),
+      testf(3.14159f),
+      testf2(3.0f),
+      testf3(0.0f) {}
 };
 
 /// an example documentation comment: monster object
@@ -767,13 +799,15 @@
   }
 }
 
-inline AnyUnion::~AnyUnion() {
+inline void AnyUnion::Reset() {
   switch (type) {
     case Any_Monster: delete reinterpret_cast<MonsterT *>(table); break;
     case Any_TestSimpleTableWithEnum: delete reinterpret_cast<TestSimpleTableWithEnumT *>(table); break;
     case Any_MyGame_Example2_Monster: delete reinterpret_cast<MyGame::Example2::MonsterT *>(table); break;
-    default:;
+    default: break;
   }
+  table = nullptr;
+  type = Any_NONE;
 }
 
 inline const MyGame::Example::Monster *GetMonster(const void *buf) {