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):
|
||||
lets a single struct declaration back a native type that is a C++
|
||||
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
|
||||
struct Box (native_type_template: "Native::Box<{{T}}>") {
|
||||
struct Box (native_type_template: "Native::Box") {
|
||||
value: int32;
|
||||
}
|
||||
|
||||
@@ -271,10 +276,10 @@ is equivalent to writing, on each field itself:
|
||||
functions stay unique across instantiations without spelling it out
|
||||
yourself; an explicit `native_type_pack_name` on the field still overrides
|
||||
this. More than one template parameter is supported by separating them with
|
||||
commas and using indexed placeholders:
|
||||
commas:
|
||||
|
||||
```cpp
|
||||
struct Pair (native_type_template: "Native::Pair<{{T0}}, {{T1}}>") {
|
||||
struct Pair (native_type_template: "Native::Pair") {
|
||||
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
|
||||
(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.
|
||||
// For a single argument, the unindexed `{{T}}` spelling is also
|
||||
// accepted (equivalent to `{{T0}}`).
|
||||
std::string native_type_str = native_type_template->constant;
|
||||
// The native type is `native_type_template`, the bare template name,
|
||||
// with the arguments appended as a trailing, angle-bracketed template
|
||||
// argument list, e.g. "Native::Box" + ["Native::TypeA"] ->
|
||||
// "Native::Box<Native::TypeA>".
|
||||
std::string native_type_str = native_type_template->constant + "<";
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
std::vector<std::string> placeholders = { "{{T" + NumToString(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;
|
||||
}
|
||||
}
|
||||
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 (i) native_type_str += ", ";
|
||||
native_type_str += 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'");
|
||||
native_type_str += ">";
|
||||
|
||||
auto native_type_val = new Value();
|
||||
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
|
||||
// struct declaration per specialization (compare to Vector3D/Vector3DAlt
|
||||
// above).
|
||||
struct Tagged (native_type_template: "Native::Tagged<{{T}}>") {
|
||||
struct Tagged (native_type_template: "Native::Tagged") {
|
||||
value:int32;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,14 +106,6 @@ void ErrorTest() {
|
||||
"struct-typed fields");
|
||||
TestError(
|
||||
"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:\"\"); }",
|
||||
"empty template argument");
|
||||
TestError("{}", "no root");
|
||||
|
||||
Reference in New Issue
Block a user