[C++] Generate default member initializers for >= C++11 (#5989)

In >= C++11 mode, generate default member initializers instead of a
default constructor.

The new code is semantically equivalent, but will allow aggregate
initialization in C++20.

This is a different take on #5951.
This commit is contained in:
Jean-François Roy
2020-06-22 18:06:15 -07:00
committed by GitHub
parent 413bb9b553
commit e5a8f76a4b
2 changed files with 86 additions and 112 deletions

View File

@@ -1652,15 +1652,38 @@ class CppGenerator : public BaseGenerator {
"> " "> "
: GenTypeNativePtr(cpp_type->constant, &field, false)) : GenTypeNativePtr(cpp_type->constant, &field, false))
: type + " "); : type + " ");
// Generate default member initializers for >= C++11.
std::string field_di = "";
if (opts_.g_cpp_std >= cpp::CPP_STD_11) {
field_di = "{}";
auto native_default = field.attributes.Lookup("native_default");
// Scalar types get parsed defaults, raw pointers get nullptrs.
if (IsScalar(field.value.type.base_type)) {
field_di =
" = " + (native_default ? std::string(native_default->constant)
: GetDefaultScalarValue(field, true));
} else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
if (IsStruct(field.value.type) && native_default) {
field_di = " = " + native_default->constant;
}
}
}
code_.SetValue("FIELD_TYPE", full_type); code_.SetValue("FIELD_TYPE", full_type);
code_.SetValue("FIELD_NAME", Name(field)); code_.SetValue("FIELD_NAME", Name(field));
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}};"; code_.SetValue("FIELD_DI", field_di);
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}{{FIELD_DI}};";
} }
} }
// Generate the default constructor for this struct. Properly initialize all // Generate the default constructor for this struct. Properly initialize all
// scalar members with default values. // scalar members with default values.
void GenDefaultConstructor(const StructDef &struct_def) { void GenDefaultConstructor(const StructDef &struct_def) {
code_.SetValue("NATIVE_NAME",
NativeName(Name(struct_def), &struct_def, opts_));
// In >= C++11, default member initializers are generated.
if (opts_.g_cpp_std >= cpp::CPP_STD_11) {
return;
}
std::string initializer_list; std::string initializer_list;
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
@@ -1698,8 +1721,6 @@ class CppGenerator : public BaseGenerator {
initializer_list = "\n : " + initializer_list; initializer_list = "\n : " + initializer_list;
} }
code_.SetValue("NATIVE_NAME",
NativeName(Name(struct_def), &struct_def, opts_));
code_.SetValue("INIT_LIST", initializer_list); code_.SetValue("INIT_LIST", initializer_list);
code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {"; code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {";

View File

@@ -625,8 +625,6 @@ FLATBUFFERS_STRUCT_END(Ability, 8);
struct InParentNamespaceT : public flatbuffers::NativeTable { struct InParentNamespaceT : public flatbuffers::NativeTable {
typedef InParentNamespace TableType; typedef InParentNamespace TableType;
InParentNamespaceT() {
}
}; };
struct InParentNamespace FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct InParentNamespace FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -677,8 +675,6 @@ namespace Example2 {
struct MonsterT : public flatbuffers::NativeTable { struct MonsterT : public flatbuffers::NativeTable {
typedef Monster TableType; typedef Monster TableType;
MonsterT() {
}
}; };
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -731,10 +727,7 @@ namespace Example {
struct TestSimpleTableWithEnumT : public flatbuffers::NativeTable { struct TestSimpleTableWithEnumT : public flatbuffers::NativeTable {
typedef TestSimpleTableWithEnum TableType; typedef TestSimpleTableWithEnum TableType;
MyGame::Example::Color color; MyGame::Example::Color color = MyGame::Example::Color::Green;
TestSimpleTableWithEnumT()
: color(MyGame::Example::Color::Green) {
}
}; };
struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -798,13 +791,9 @@ flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatb
struct StatT : public flatbuffers::NativeTable { struct StatT : public flatbuffers::NativeTable {
typedef Stat TableType; typedef Stat TableType;
std::string id; std::string id{};
int64_t val; int64_t val = 0;
uint16_t count; uint16_t count = 0;
StatT()
: val(0),
count(0) {
}
}; };
struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -908,10 +897,7 @@ flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const
struct ReferrableT : public flatbuffers::NativeTable { struct ReferrableT : public flatbuffers::NativeTable {
typedef Referrable TableType; typedef Referrable TableType;
uint64_t id; uint64_t id = 0;
ReferrableT()
: id(0) {
}
}; };
struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -981,72 +967,51 @@ flatbuffers::Offset<Referrable> CreateReferrable(flatbuffers::FlatBufferBuilder
struct MonsterT : public flatbuffers::NativeTable { struct MonsterT : public flatbuffers::NativeTable {
typedef Monster TableType; typedef Monster TableType;
std::unique_ptr<MyGame::Example::Vec3> pos; std::unique_ptr<MyGame::Example::Vec3> pos{};
int16_t mana; int16_t mana = 150;
int16_t hp; int16_t hp = 100;
std::string name; std::string name{};
std::vector<uint8_t> inventory; std::vector<uint8_t> inventory{};
MyGame::Example::Color color; MyGame::Example::Color color = MyGame::Example::Color::Blue;
MyGame::Example::AnyUnion test; MyGame::Example::AnyUnion test{};
std::vector<MyGame::Example::Test> test4; std::vector<MyGame::Example::Test> test4{};
std::vector<std::string> testarrayofstring; std::vector<std::string> testarrayofstring{};
std::vector<std::unique_ptr<MyGame::Example::MonsterT>> testarrayoftables; std::vector<std::unique_ptr<MyGame::Example::MonsterT>> testarrayoftables{};
std::unique_ptr<MyGame::Example::MonsterT> enemy; std::unique_ptr<MyGame::Example::MonsterT> enemy{};
std::vector<uint8_t> testnestedflatbuffer; std::vector<uint8_t> testnestedflatbuffer{};
std::unique_ptr<MyGame::Example::StatT> testempty; std::unique_ptr<MyGame::Example::StatT> testempty{};
bool testbool; bool testbool = false;
int32_t testhashs32_fnv1; int32_t testhashs32_fnv1 = 0;
uint32_t testhashu32_fnv1; uint32_t testhashu32_fnv1 = 0;
int64_t testhashs64_fnv1; int64_t testhashs64_fnv1 = 0;
uint64_t testhashu64_fnv1; uint64_t testhashu64_fnv1 = 0;
int32_t testhashs32_fnv1a; int32_t testhashs32_fnv1a = 0;
Stat *testhashu32_fnv1a; Stat *testhashu32_fnv1a = nullptr;
int64_t testhashs64_fnv1a; int64_t testhashs64_fnv1a = 0;
uint64_t testhashu64_fnv1a; uint64_t testhashu64_fnv1a = 0;
std::vector<bool> testarrayofbools; std::vector<bool> testarrayofbools{};
float testf; float testf = 3.14159f;
float testf2; float testf2 = 3.0f;
float testf3; float testf3 = 0.0f;
std::vector<std::string> testarrayofstring2; std::vector<std::string> testarrayofstring2{};
std::vector<MyGame::Example::Ability> testarrayofsortedstruct; std::vector<MyGame::Example::Ability> testarrayofsortedstruct{};
std::vector<uint8_t> flex; std::vector<uint8_t> flex{};
std::vector<MyGame::Example::Test> test5; std::vector<MyGame::Example::Test> test5{};
std::vector<int64_t> vector_of_longs; std::vector<int64_t> vector_of_longs{};
std::vector<double> vector_of_doubles; std::vector<double> vector_of_doubles{};
std::unique_ptr<MyGame::InParentNamespaceT> parent_namespace_test; std::unique_ptr<MyGame::InParentNamespaceT> parent_namespace_test{};
std::vector<std::unique_ptr<MyGame::Example::ReferrableT>> vector_of_referrables; std::vector<std::unique_ptr<MyGame::Example::ReferrableT>> vector_of_referrables{};
ReferrableT *single_weak_reference; ReferrableT *single_weak_reference = nullptr;
std::vector<ReferrableT *> vector_of_weak_references; std::vector<ReferrableT *> vector_of_weak_references{};
std::vector<std::unique_ptr<MyGame::Example::ReferrableT>> vector_of_strong_referrables; std::vector<std::unique_ptr<MyGame::Example::ReferrableT>> vector_of_strong_referrables{};
ReferrableT *co_owning_reference; ReferrableT *co_owning_reference = nullptr;
std::vector<std::unique_ptr<ReferrableT>> vector_of_co_owning_references; std::vector<std::unique_ptr<ReferrableT>> vector_of_co_owning_references{};
ReferrableT *non_owning_reference; ReferrableT *non_owning_reference = nullptr;
std::vector<ReferrableT *> vector_of_non_owning_references; std::vector<ReferrableT *> vector_of_non_owning_references{};
MyGame::Example::AnyUniqueAliasesUnion any_unique; MyGame::Example::AnyUniqueAliasesUnion any_unique{};
MyGame::Example::AnyAmbiguousAliasesUnion any_ambiguous; MyGame::Example::AnyAmbiguousAliasesUnion any_ambiguous{};
std::vector<MyGame::Example::Color> vector_of_enums; std::vector<MyGame::Example::Color> vector_of_enums{};
MyGame::Example::Race signed_enum; MyGame::Example::Race signed_enum = MyGame::Example::Race::None;
MonsterT()
: mana(150),
hp(100),
color(MyGame::Example::Color::Blue),
testbool(false),
testhashs32_fnv1(0),
testhashu32_fnv1(0),
testhashs64_fnv1(0),
testhashu64_fnv1(0),
testhashs32_fnv1a(0),
testhashu32_fnv1a(nullptr),
testhashs64_fnv1a(0),
testhashu64_fnv1a(0),
testf(3.14159f),
testf2(3.0f),
testf3(0.0f),
single_weak_reference(nullptr),
co_owning_reference(nullptr),
non_owning_reference(nullptr),
signed_enum(MyGame::Example::Race::None) {
}
}; };
/// an example documentation comment: "monster object" /// an example documentation comment: "monster object"
@@ -1932,30 +1897,18 @@ flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
struct TypeAliasesT : public flatbuffers::NativeTable { struct TypeAliasesT : public flatbuffers::NativeTable {
typedef TypeAliases TableType; typedef TypeAliases TableType;
int8_t i8; int8_t i8 = 0;
uint8_t u8; uint8_t u8 = 0;
int16_t i16; int16_t i16 = 0;
uint16_t u16; uint16_t u16 = 0;
int32_t i32; int32_t i32 = 0;
uint32_t u32; uint32_t u32 = 0;
int64_t i64; int64_t i64 = 0;
uint64_t u64; uint64_t u64 = 0;
float f32; float f32 = 0.0f;
double f64; double f64 = 0.0;
std::vector<int8_t> v8; std::vector<int8_t> v8{};
std::vector<double> vf64; std::vector<double> vf64{};
TypeAliasesT()
: i8(0),
u8(0),
i16(0),
u16(0),
i32(0),
u32(0),
i64(0),
u64(0),
f32(0.0f),
f64(0.0) {
}
}; };
struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {