aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid P. Sicilia <dpacbach@users.noreply.github.com>2020-01-02 13:12:14 -0500
committerWouter van Oortmerssen <aardappel@gmail.com>2020-01-02 10:12:14 -0800
commita5d9d0f7d368054fd1691aedf1db4116efcc233e (patch)
tree8d252e4ad24f5cd6331f70a09aa1dcad166037da
parent3cd9b6434a6f4ec5ee6c49d1b9fd58209d714e82 (diff)
downloadflatbuffers-a5d9d0f7d368054fd1691aedf1db4116efcc233e.tar.gz
[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.
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/idl_gen_cpp.cpp13
-rw-r--r--tests/cpp17/generated_cpp17/monster_test_generated.h42
-rw-r--r--tests/cpp17/test_cpp17.cpp25
4 files changed, 82 insertions, 1 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3d4ecc81..2fed2019 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -530,6 +530,9 @@ if(FLATBUFFERS_BUILD_TESTS)
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION
"${CMAKE_CURRENT_BINARY_DIR}")
add_test(NAME flattests COMMAND flattests)
+ if(FLATBUFFERS_BUILD_CPP17)
+ add_test(NAME flattests_cpp17 COMMAND flattests_cpp17)
+ endif()
if(FLATBUFFERS_BUILD_GRPCTEST)
add_test(NAME grpctest COMMAND grpctest)
endif()
diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp
index 12e43375..f74abbf8 100644
--- a/src/idl_gen_cpp.cpp
+++ b/src/idl_gen_cpp.cpp
@@ -1837,6 +1837,9 @@ class CppGenerator : public BaseGenerator {
code_ += " typedef {{NATIVE_NAME}} NativeTableType;";
}
code_ += " typedef {{STRUCT_NAME}}Builder Builder;";
+ if (opts_.g_cpp_std >= cpp::CPP_STD_17) {
+ code_ += " struct Traits;";
+ }
if (opts_.mini_reflect != IDLOptions::kNone) {
code_ +=
" static const flatbuffers::TypeTable *MiniReflectTypeTable() {";
@@ -2198,6 +2201,16 @@ class CppGenerator : public BaseGenerator {
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
if (has_string_or_vector_fields) {
code_ +=
diff --git a/tests/cpp17/generated_cpp17/monster_test_generated.h b/tests/cpp17/generated_cpp17/monster_test_generated.h
index ea29cfc5..a43c12ff 100644
--- a/tests/cpp17/generated_cpp17/monster_test_generated.h
+++ b/tests/cpp17/generated_cpp17/monster_test_generated.h
@@ -621,6 +621,7 @@ struct InParentNamespaceT : public flatbuffers::NativeTable {
struct InParentNamespace FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef InParentNamespaceT NativeTableType;
typedef InParentNamespaceBuilder Builder;
+ struct Traits;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return InParentNamespaceTypeTable();
}
@@ -655,6 +656,11 @@ inline flatbuffers::Offset<InParentNamespace> CreateInParentNamespace(
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);
namespace Example2 {
@@ -668,6 +674,7 @@ struct MonsterT : public flatbuffers::NativeTable {
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef MonsterT NativeTableType;
typedef MonsterBuilder Builder;
+ struct Traits;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return MonsterTypeTable();
}
@@ -702,6 +709,11 @@ inline flatbuffers::Offset<Monster> CreateMonster(
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);
} // namespace Example2
@@ -719,6 +731,7 @@ struct TestSimpleTableWithEnumT : public flatbuffers::NativeTable {
struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef TestSimpleTableWithEnumT NativeTableType;
typedef TestSimpleTableWithEnumBuilder Builder;
+ struct Traits;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return TestSimpleTableWithEnumTypeTable();
}
@@ -768,6 +781,11 @@ inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnu
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);
struct StatT : public flatbuffers::NativeTable {
@@ -784,6 +802,7 @@ struct StatT : public flatbuffers::NativeTable {
struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef StatT NativeTableType;
typedef StatBuilder Builder;
+ struct Traits;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return StatTypeTable();
}
@@ -860,6 +879,11 @@ inline flatbuffers::Offset<Stat> CreateStat(
return builder_.Finish();
}
+struct Stat::Traits {
+ using type = Stat;
+ static auto constexpr Create = CreateStat;
+};
+
inline flatbuffers::Offset<Stat> CreateStatDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *id = nullptr,
@@ -886,6 +910,7 @@ struct ReferrableT : public flatbuffers::NativeTable {
struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef ReferrableT NativeTableType;
typedef ReferrableBuilder Builder;
+ struct Traits;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return ReferrableTypeTable();
}
@@ -941,6 +966,11 @@ inline flatbuffers::Offset<Referrable> CreateReferrable(
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);
struct MonsterT : public flatbuffers::NativeTable {
@@ -1017,6 +1047,7 @@ struct MonsterT : public flatbuffers::NativeTable {
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef MonsterT NativeTableType;
typedef MonsterBuilder Builder;
+ struct Traits;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return MonsterTypeTable();
}
@@ -1766,6 +1797,11 @@ inline flatbuffers::Offset<Monster> CreateMonster(
return builder_.Finish();
}
+struct Monster::Traits {
+ using type = Monster;
+ static auto constexpr Create = CreateMonster;
+};
+
inline flatbuffers::Offset<Monster> CreateMonsterDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const MyGame::Example::Vec3 *pos = 0,
@@ -1920,6 +1956,7 @@ struct TypeAliasesT : public flatbuffers::NativeTable {
struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef TypeAliasesT NativeTableType;
typedef TypeAliasesBuilder Builder;
+ struct Traits;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return TypeAliasesTypeTable();
}
@@ -2114,6 +2151,11 @@ inline flatbuffers::Offset<TypeAliases> CreateTypeAliases(
return builder_.Finish();
}
+struct TypeAliases::Traits {
+ using type = TypeAliases;
+ static auto constexpr Create = CreateTypeAliases;
+};
+
inline flatbuffers::Offset<TypeAliases> CreateTypeAliasesDirect(
flatbuffers::FlatBufferBuilder &_fbb,
int8_t i8 = 0,
diff --git a/tests/cpp17/test_cpp17.cpp b/tests/cpp17/test_cpp17.cpp
index 291aa838..91390bda 100644
--- a/tests/cpp17/test_cpp17.cpp
+++ b/tests/cpp17/test_cpp17.cpp
@@ -36,8 +36,31 @@ namespace cpp11 {
#include "../monster_test_generated.h"
} // 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() {
- TEST_ASSERT(true);
+ CreateTableByTypeTest();
return 0;
}