Add default values (if they exist) to native tables.

From cl/142307012.

Change-Id: I54d550573f6506b92ad18e7cc90bcd8589259e52
diff --git a/samples/monster_generated.h b/samples/monster_generated.h
index 2504e83..ded7846 100644
--- a/samples/monster_generated.h
+++ b/samples/monster_generated.h
@@ -111,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 {
@@ -228,6 +232,8 @@
   typedef Weapon TableType;
   std::string name;
   int16_t damage;
+  WeaponT()
+    : damage(0) {}
 };
 
 struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index 8e33b59..0436f4d 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -691,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;
@@ -726,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 8a2a111..5714f58 100644
--- a/tests/monster_test_generated.h
+++ b/tests/monster_test_generated.h
@@ -162,6 +162,7 @@
 
 struct MonsterT : public flatbuffers::NativeTable {
   typedef Monster TableType;
+  MonsterT() {}
 };
 
 struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -199,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 {
@@ -243,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 {
@@ -333,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