mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-28 06:08:06 +00:00
[C++17] Add Traits class for Tables and Factory function within it. (#5678)
* Include flattests_cpp17 in unit tests when C++17 build is enabled.
* [C++17] Generate generic table factory function.
1. For each table, generate a convenient free-standing factory
function that allows creating the table in a generic way by
specifying only the type. This is the first change in a series
of changes to make Flatbuffers generated C++ code more friendly
to code bases that make use of C++ template metaprogramming
techniques to manage the serialization process. Example:
Before :(
// The name of the Flatbuffers type (and namespace) must
// be hard-coded when writing the factory function.
auto monster = MyGame::Example::CreateMonster(fbb, ...);
After :)
using type_to_create = MyGame::Example::Monster;
// No namespace needed on CreateByTagType.
auto monster = CreateByTagType((type_to_create*)nullptr,
fbb, ...);
This feature requires building with C++14 or greater, and thus
it is guarded behind --cpp-std >= c++17 in the flatbuffers C++
generator.
2. Fix a CMake bug to include C++17 unit tests in test suite.
* [C++17] Replace standalone variadic factory function with type_traits.
Add a `type_traits` to each table class. This `type_traits` can be
populated with various compile-time info about the table. Initially,
we have the Create* function and type, but is extensible in the future.
* Remove empty line and fix stale comments.
* Rename type_traits to Traits and move fwd declaration.
* Fix parameter evaluation order issue and use lambda for scope.
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
3cd9b6434a
commit
a5d9d0f7d3
@@ -530,6 +530,9 @@ if(FLATBUFFERS_BUILD_TESTS)
|
|||||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION
|
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
add_test(NAME flattests COMMAND flattests)
|
add_test(NAME flattests COMMAND flattests)
|
||||||
|
if(FLATBUFFERS_BUILD_CPP17)
|
||||||
|
add_test(NAME flattests_cpp17 COMMAND flattests_cpp17)
|
||||||
|
endif()
|
||||||
if(FLATBUFFERS_BUILD_GRPCTEST)
|
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||||
add_test(NAME grpctest COMMAND grpctest)
|
add_test(NAME grpctest COMMAND grpctest)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1837,6 +1837,9 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code_ += " typedef {{NATIVE_NAME}} NativeTableType;";
|
code_ += " typedef {{NATIVE_NAME}} NativeTableType;";
|
||||||
}
|
}
|
||||||
code_ += " typedef {{STRUCT_NAME}}Builder Builder;";
|
code_ += " typedef {{STRUCT_NAME}}Builder Builder;";
|
||||||
|
if (opts_.g_cpp_std >= cpp::CPP_STD_17) {
|
||||||
|
code_ += " struct Traits;";
|
||||||
|
}
|
||||||
if (opts_.mini_reflect != IDLOptions::kNone) {
|
if (opts_.mini_reflect != IDLOptions::kNone) {
|
||||||
code_ +=
|
code_ +=
|
||||||
" static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
|
" static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
|
||||||
@@ -2198,6 +2201,16 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code_ += "}";
|
code_ += "}";
|
||||||
code_ += "";
|
code_ += "";
|
||||||
|
|
||||||
|
// Definition for type traits for this table type. This allows querying var-
|
||||||
|
// ious compile-time traits of the table.
|
||||||
|
if (opts_.g_cpp_std >= cpp::CPP_STD_17) {
|
||||||
|
code_ += "struct {{STRUCT_NAME}}::Traits {";
|
||||||
|
code_ += " using type = {{STRUCT_NAME}};";
|
||||||
|
code_ += " static auto constexpr Create = Create{{STRUCT_NAME}};";
|
||||||
|
code_ += "};";
|
||||||
|
code_ += "";
|
||||||
|
}
|
||||||
|
|
||||||
// Generate a CreateXDirect function with vector types as parameters
|
// Generate a CreateXDirect function with vector types as parameters
|
||||||
if (has_string_or_vector_fields) {
|
if (has_string_or_vector_fields) {
|
||||||
code_ +=
|
code_ +=
|
||||||
|
|||||||
@@ -621,6 +621,7 @@ struct InParentNamespaceT : public flatbuffers::NativeTable {
|
|||||||
struct InParentNamespace FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct InParentNamespace FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
typedef InParentNamespaceT NativeTableType;
|
typedef InParentNamespaceT NativeTableType;
|
||||||
typedef InParentNamespaceBuilder Builder;
|
typedef InParentNamespaceBuilder Builder;
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return InParentNamespaceTypeTable();
|
return InParentNamespaceTypeTable();
|
||||||
}
|
}
|
||||||
@@ -655,6 +656,11 @@ inline flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct InParentNamespace::Traits {
|
||||||
|
using type = InParentNamespace;
|
||||||
|
static auto constexpr Create = CreateInParentNamespace;
|
||||||
|
};
|
||||||
|
|
||||||
flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(flatbuffers::FlatBufferBuilder &_fbb, const InParentNamespaceT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(flatbuffers::FlatBufferBuilder &_fbb, const InParentNamespaceT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
|
|
||||||
namespace Example2 {
|
namespace Example2 {
|
||||||
@@ -668,6 +674,7 @@ struct MonsterT : public flatbuffers::NativeTable {
|
|||||||
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
typedef MonsterT NativeTableType;
|
typedef MonsterT NativeTableType;
|
||||||
typedef MonsterBuilder Builder;
|
typedef MonsterBuilder Builder;
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return MonsterTypeTable();
|
return MonsterTypeTable();
|
||||||
}
|
}
|
||||||
@@ -702,6 +709,11 @@ inline flatbuffers::Offset<Monster> CreateMonster(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Monster::Traits {
|
||||||
|
using type = Monster;
|
||||||
|
static auto constexpr Create = CreateMonster;
|
||||||
|
};
|
||||||
|
|
||||||
flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
|
|
||||||
} // namespace Example2
|
} // namespace Example2
|
||||||
@@ -719,6 +731,7 @@ struct TestSimpleTableWithEnumT : public flatbuffers::NativeTable {
|
|||||||
struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
typedef TestSimpleTableWithEnumT NativeTableType;
|
typedef TestSimpleTableWithEnumT NativeTableType;
|
||||||
typedef TestSimpleTableWithEnumBuilder Builder;
|
typedef TestSimpleTableWithEnumBuilder Builder;
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return TestSimpleTableWithEnumTypeTable();
|
return TestSimpleTableWithEnumTypeTable();
|
||||||
}
|
}
|
||||||
@@ -768,6 +781,11 @@ inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnu
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TestSimpleTableWithEnum::Traits {
|
||||||
|
using type = TestSimpleTableWithEnum;
|
||||||
|
static auto constexpr Create = CreateTestSimpleTableWithEnum;
|
||||||
|
};
|
||||||
|
|
||||||
flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
|
|
||||||
struct StatT : public flatbuffers::NativeTable {
|
struct StatT : public flatbuffers::NativeTable {
|
||||||
@@ -784,6 +802,7 @@ struct StatT : public flatbuffers::NativeTable {
|
|||||||
struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
typedef StatT NativeTableType;
|
typedef StatT NativeTableType;
|
||||||
typedef StatBuilder Builder;
|
typedef StatBuilder Builder;
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return StatTypeTable();
|
return StatTypeTable();
|
||||||
}
|
}
|
||||||
@@ -860,6 +879,11 @@ inline flatbuffers::Offset<Stat> CreateStat(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Stat::Traits {
|
||||||
|
using type = Stat;
|
||||||
|
static auto constexpr Create = CreateStat;
|
||||||
|
};
|
||||||
|
|
||||||
inline flatbuffers::Offset<Stat> CreateStatDirect(
|
inline flatbuffers::Offset<Stat> CreateStatDirect(
|
||||||
flatbuffers::FlatBufferBuilder &_fbb,
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
const char *id = nullptr,
|
const char *id = nullptr,
|
||||||
@@ -886,6 +910,7 @@ struct ReferrableT : public flatbuffers::NativeTable {
|
|||||||
struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
typedef ReferrableT NativeTableType;
|
typedef ReferrableT NativeTableType;
|
||||||
typedef ReferrableBuilder Builder;
|
typedef ReferrableBuilder Builder;
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return ReferrableTypeTable();
|
return ReferrableTypeTable();
|
||||||
}
|
}
|
||||||
@@ -941,6 +966,11 @@ inline flatbuffers::Offset<Referrable> CreateReferrable(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Referrable::Traits {
|
||||||
|
using type = Referrable;
|
||||||
|
static auto constexpr Create = CreateReferrable;
|
||||||
|
};
|
||||||
|
|
||||||
flatbuffers::Offset<Referrable> CreateReferrable(flatbuffers::FlatBufferBuilder &_fbb, const ReferrableT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
flatbuffers::Offset<Referrable> CreateReferrable(flatbuffers::FlatBufferBuilder &_fbb, const ReferrableT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||||
|
|
||||||
struct MonsterT : public flatbuffers::NativeTable {
|
struct MonsterT : public flatbuffers::NativeTable {
|
||||||
@@ -1017,6 +1047,7 @@ struct MonsterT : public flatbuffers::NativeTable {
|
|||||||
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
typedef MonsterT NativeTableType;
|
typedef MonsterT NativeTableType;
|
||||||
typedef MonsterBuilder Builder;
|
typedef MonsterBuilder Builder;
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return MonsterTypeTable();
|
return MonsterTypeTable();
|
||||||
}
|
}
|
||||||
@@ -1766,6 +1797,11 @@ inline flatbuffers::Offset<Monster> CreateMonster(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Monster::Traits {
|
||||||
|
using type = Monster;
|
||||||
|
static auto constexpr Create = CreateMonster;
|
||||||
|
};
|
||||||
|
|
||||||
inline flatbuffers::Offset<Monster> CreateMonsterDirect(
|
inline flatbuffers::Offset<Monster> CreateMonsterDirect(
|
||||||
flatbuffers::FlatBufferBuilder &_fbb,
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
const MyGame::Example::Vec3 *pos = 0,
|
const MyGame::Example::Vec3 *pos = 0,
|
||||||
@@ -1920,6 +1956,7 @@ struct TypeAliasesT : public flatbuffers::NativeTable {
|
|||||||
struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
typedef TypeAliasesT NativeTableType;
|
typedef TypeAliasesT NativeTableType;
|
||||||
typedef TypeAliasesBuilder Builder;
|
typedef TypeAliasesBuilder Builder;
|
||||||
|
struct Traits;
|
||||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||||
return TypeAliasesTypeTable();
|
return TypeAliasesTypeTable();
|
||||||
}
|
}
|
||||||
@@ -2114,6 +2151,11 @@ inline flatbuffers::Offset<TypeAliases> CreateTypeAliases(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TypeAliases::Traits {
|
||||||
|
using type = TypeAliases;
|
||||||
|
static auto constexpr Create = CreateTypeAliases;
|
||||||
|
};
|
||||||
|
|
||||||
inline flatbuffers::Offset<TypeAliases> CreateTypeAliasesDirect(
|
inline flatbuffers::Offset<TypeAliases> CreateTypeAliasesDirect(
|
||||||
flatbuffers::FlatBufferBuilder &_fbb,
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
int8_t i8 = 0,
|
int8_t i8 = 0,
|
||||||
|
|||||||
@@ -36,8 +36,31 @@ namespace cpp11 {
|
|||||||
#include "../monster_test_generated.h"
|
#include "../monster_test_generated.h"
|
||||||
} // namespace cpp11
|
} // namespace cpp11
|
||||||
|
|
||||||
|
void CreateTableByTypeTest() {
|
||||||
|
flatbuffers::FlatBufferBuilder builder;
|
||||||
|
|
||||||
|
// We will create an object of this type using only the type.
|
||||||
|
using type_to_create_t = cpp17::MyGame::Example::Stat;
|
||||||
|
|
||||||
|
[&builder] {
|
||||||
|
auto id_str = builder.CreateString("my_id");
|
||||||
|
auto table = type_to_create_t::Traits::Create(builder, id_str, 42, 7);
|
||||||
|
// Be sure that the correct return type was inferred.
|
||||||
|
static_assert(
|
||||||
|
std::is_same_v<decltype(table), flatbuffers::Offset<type_to_create_t>>);
|
||||||
|
builder.Finish(table);
|
||||||
|
}();
|
||||||
|
|
||||||
|
// Access it.
|
||||||
|
auto stat =
|
||||||
|
flatbuffers::GetRoot<type_to_create_t>(builder.GetBufferPointer());
|
||||||
|
TEST_EQ_STR(stat->id()->c_str(), "my_id");
|
||||||
|
TEST_EQ(stat->val(), 42);
|
||||||
|
TEST_EQ(stat->count(), 7);
|
||||||
|
}
|
||||||
|
|
||||||
int FlatBufferCpp17Tests() {
|
int FlatBufferCpp17Tests() {
|
||||||
TEST_ASSERT(true);
|
CreateTableByTypeTest();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user