Add c++ "init structs" for chained struct types
Chained structs can't currently use designated initializers. This
is because aggregate initialization is not supported when the
struct has a constructor. The constructor defaults the sType.
To allow for a sort of aggregate initialization with designated
initializers, add an Init struct from which the struct can be
constructed. This allows for aggregate-looking construction
with mostly the same syntax. You can now construct a chained struct
with double-braces (instead of single) like:
```
MyChainedStruct {{
.foo = 42,
.bar = "hello!",
}};
```
Bug: chromium:40195122
Change-Id: I05e99335f48dd56ee7cdc0c4539111c630c70d8a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/185967
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/generator/templates/api_cpp.h b/generator/templates/api_cpp.h
index 9790a50..f450d30 100644
--- a/generator/templates/api_cpp.h
+++ b/generator/templates/api_cpp.h
@@ -320,13 +320,14 @@
// Can be chained in {{as_cppType(root.name)}}
{% endfor %}
struct {{as_cppType(type.name)}} : ChainedStruct{{Out}} {
- {{as_cppType(type.name)}}() {
- sType = SType::{{type.name.CamelCase()}};
- }
+ inline {{as_cppType(type.name)}}();
+
+ struct Init;
+ inline {{as_cppType(type.name)}}(Init&& init);
{% else %}
struct {{as_cppType(type.name)}} {
{% if type.has_free_members_function %}
- {{as_cppType(type.name)}}() = default;
+ inline {{as_cppType(type.name)}}();
{% endif %}
{% endif %}
{% if type.has_free_members_function %}
@@ -370,6 +371,27 @@
{% set CppType = as_cppType(type.name) %}
{% set CType = as_cType(type.name) %}
// {{CppType}} implementation
+ {% if type.chained %}
+ {% set Out = "Out" if type.output else "" %}
+ {% set const = "const" if not type.output else "" %}
+ {{CppType}}::{{CppType}}()
+ : ChainedStruct{{Out}} { nullptr, SType::{{type.name.CamelCase()}} } {}
+ struct {{CppType}}::Init {
+ ChainedStruct{{Out}} * {{const}} nextInChain;
+ {% for member in type.members %}
+ {% set member_declaration = as_annotated_cppType(member, type.has_free_members_function) + render_cpp_default_value(member, True, type.has_free_members_function) %}
+ {{member_declaration}};
+ {% endfor %}
+ };
+ {{CppType}}::{{CppType}}({{CppType}}::Init&& init)
+ : ChainedStruct{{Out}} { init.nextInChain, SType::{{type.name.CamelCase()}} }
+ {%- for member in type.members -%},{{" "}}
+ {{as_varName(member.name)}}(std::move(init.{{as_varName(member.name)}}))
+ {%- endfor -%}
+ {}
+ {% elif type.has_free_members_function %}
+ {{CppType}}::{{CppType}}() = default;
+ {% endif %}
{% if type.has_free_members_function %}
{{CppType}}::~{{CppType}}() {
if (