forked from BigfootDev/flatbuffers
Simplify templates
This commit is contained in:
@@ -242,14 +242,19 @@ provide the following functions to aide in the serialization process:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `native_type_template("type<{{T}}>")` (on a struct) together with
|
- `native_type_template("type")` (on a struct) together with
|
||||||
`native_type_template_arg("type")` (on a field of that struct type):
|
`native_type_template_arg("type")` (on a field of that struct type):
|
||||||
lets a single struct declaration back a native type that is a C++
|
lets a single struct declaration back a native type that is a C++
|
||||||
template, instantiated differently per field, instead of requiring one
|
template, instantiated differently per field, instead of requiring one
|
||||||
struct declaration (and `native_type`) per instantiation. For example:
|
struct declaration (and `native_type`) per instantiation.
|
||||||
|
`native_type_template_arg` is angle-bracket-appended to
|
||||||
|
`native_type_template` to form the field's native type, so
|
||||||
|
`native_type_template: "Native::Box"` with
|
||||||
|
`native_type_template_arg: "Native::TypeA"` produces
|
||||||
|
`Native::Box<Native::TypeA>`. For example:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
struct Box (native_type_template: "Native::Box<{{T}}>") {
|
struct Box (native_type_template: "Native::Box") {
|
||||||
value: int32;
|
value: int32;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,10 +276,10 @@ is equivalent to writing, on each field itself:
|
|||||||
functions stay unique across instantiations without spelling it out
|
functions stay unique across instantiations without spelling it out
|
||||||
yourself; an explicit `native_type_pack_name` on the field still overrides
|
yourself; an explicit `native_type_pack_name` on the field still overrides
|
||||||
this. More than one template parameter is supported by separating them with
|
this. More than one template parameter is supported by separating them with
|
||||||
commas and using indexed placeholders:
|
commas:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
struct Pair (native_type_template: "Native::Pair<{{T0}}, {{T1}}>") {
|
struct Pair (native_type_template: "Native::Pair") {
|
||||||
value: int32;
|
value: int32;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,6 +288,7 @@ commas and using indexed placeholders:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
which produces `Native::Pair<Native::Key, Native::Value>`.
|
||||||
`native_type_template_arg` is only valid on fields whose type is a struct
|
`native_type_template_arg` is only valid on fields whose type is a struct
|
||||||
(or vector of structs) that declares `native_type_template`.
|
(or vector of structs) that declares `native_type_template`.
|
||||||
|
|
||||||
|
|||||||
+8
-27
@@ -1337,35 +1337,16 @@ CheckedError Parser::ParseField(StructDef& struct_def) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Substitute each argument for its placeholder: `{{T0}}`, `{{T1}}`, etc.
|
// The native type is `native_type_template`, the bare template name,
|
||||||
// For a single argument, the unindexed `{{T}}` spelling is also
|
// with the arguments appended as a trailing, angle-bracketed template
|
||||||
// accepted (equivalent to `{{T0}}`).
|
// argument list, e.g. "Native::Box" + ["Native::TypeA"] ->
|
||||||
std::string native_type_str = native_type_template->constant;
|
// "Native::Box<Native::TypeA>".
|
||||||
|
std::string native_type_str = native_type_template->constant + "<";
|
||||||
for (size_t i = 0; i < args.size(); ++i) {
|
for (size_t i = 0; i < args.size(); ++i) {
|
||||||
std::vector<std::string> placeholders = { "{{T" + NumToString(i) +
|
if (i) native_type_str += ", ";
|
||||||
"}}" };
|
native_type_str += args[i];
|
||||||
if (i == 0) placeholders.push_back("{{T}}");
|
|
||||||
size_t replaced = 0;
|
|
||||||
for (const auto& placeholder : placeholders) {
|
|
||||||
for (;;) {
|
|
||||||
const auto pos = native_type_str.find(placeholder);
|
|
||||||
if (pos == std::string::npos) break;
|
|
||||||
native_type_str.replace(pos, placeholder.length(), args[i]);
|
|
||||||
++replaced;
|
|
||||||
}
|
}
|
||||||
}
|
native_type_str += ">";
|
||||||
if (!replaced)
|
|
||||||
return Error("'native_type_template' on '" + target_struct->name +
|
|
||||||
"' does not reference the '{{T" + NumToString(i) +
|
|
||||||
"}}' placeholder required for template argument " +
|
|
||||||
NumToString(i + 1) + " ('" + args[i] + "')");
|
|
||||||
}
|
|
||||||
if (native_type_str.find("{{T") != std::string::npos)
|
|
||||||
return Error(
|
|
||||||
"'native_type_template' on '" + target_struct->name +
|
|
||||||
"' references a '{{T<n>}}' placeholder beyond the " +
|
|
||||||
NumToString(args.size()) +
|
|
||||||
" template argument(s) given in 'native_type_template_arg'");
|
|
||||||
|
|
||||||
auto native_type_val = new Value();
|
auto native_type_val = new Value();
|
||||||
native_type_val->type = native_type_template_arg->type;
|
native_type_val->type = native_type_template_arg->type;
|
||||||
|
|||||||
@@ -24,12 +24,12 @@ table Matrix (native_type:"Native::Matrix") {
|
|||||||
// field via `native_type_template_arg` instead of needing one flatbuffers
|
// field via `native_type_template_arg` instead of needing one flatbuffers
|
||||||
// struct declaration per specialization (compare to Vector3D/Vector3DAlt
|
// struct declaration per specialization (compare to Vector3D/Vector3DAlt
|
||||||
// above).
|
// above).
|
||||||
struct Tagged (native_type_template: "Native::Tagged<{{T}}>") {
|
struct Tagged (native_type_template: "Native::Tagged") {
|
||||||
value:int32;
|
value:int32;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A native type template that takes more than one argument.
|
// A native type template that takes more than one argument.
|
||||||
struct Pair (native_type_template: "Native::Pair<{{T0}}, {{T1}}>") {
|
struct Pair (native_type_template: "Native::Pair") {
|
||||||
value:int32;
|
value:int32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,14 +106,6 @@ void ErrorTest() {
|
|||||||
"struct-typed fields");
|
"struct-typed fields");
|
||||||
TestError(
|
TestError(
|
||||||
"struct X (native_type_template: \"Foo\") { Y:int; } "
|
"struct X (native_type_template: \"Foo\") { Y:int; } "
|
||||||
"table T { y:X (native_type_template_arg:\"int\"); }",
|
|
||||||
"does not reference");
|
|
||||||
TestError(
|
|
||||||
"struct X (native_type_template: \"Foo<{{T0}}, {{T1}}>\") { Y:int; } "
|
|
||||||
"table T { y:X (native_type_template_arg:\"int\"); }",
|
|
||||||
"beyond the");
|
|
||||||
TestError(
|
|
||||||
"struct X (native_type_template: \"Foo<{{T}}>\") { Y:int; } "
|
|
||||||
"table T { y:X (native_type_template_arg:\"\"); }",
|
"table T { y:X (native_type_template_arg:\"\"); }",
|
||||||
"empty template argument");
|
"empty template argument");
|
||||||
TestError("{}", "no root");
|
TestError("{}", "no root");
|
||||||
|
|||||||
Reference in New Issue
Block a user