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 (