void writeTypeDeclarations(Writer w, CNode node, String indent) throws IOException {
        java.util.Set<String> declaredTypes = new java.util.HashSet<>();
        for (CNode child : node.getChildren()) {
            boolean complexType = (child instanceof InnerCNode || child instanceof LeafCNode.EnumLeaf);
            if (complexType && !declaredTypes.contains(child.getName())) {
                String typeName = getTypeName(child, false);
                declaredTypes.add(child.getName());
                if (child instanceof LeafCNode.EnumLeaf) {
                    w.write(indent + "enum class " + typeName + " { ");
                    LeafCNode.EnumLeaf leaf = (LeafCNode.EnumLeaf) child;
                    for (int i=0; i<leaf.getLegalValues().length; ++i) {
                        if (i != 0) {
                            w.write(", ");
                        }
                        w.write(leaf.getLegalValues()[i]);
                    }
                    w.write(" };\n"
                            + indent + "typedef std::vector<" + typeName + "> "
                            + typeName + "Vector;"
                            + "\n"
                            + indent + "typedef std::map<std::string, " + typeName + "> "
                            + typeName + "Map;"
                            + "\n"
                            + indent + "static " + typeName + " get" + typeName + "(const std::string&);\n"
                            + indent + "static std::string get" + typeName + "Name(" + typeName + " e);\n"
                            + "\n"
                            );
                    w.write(indent + "struct Internal" + typeName + "Converter {\n");
                    w.write(indent + "    " + typeName + " operator()(const ::std::string & __fieldName, const ::vespalib::slime::Inspector & __inspector);\n");
                    w.write(indent + "    " + typeName + " operator()(const ::vespalib::slime::Inspector & __inspector);\n");
                    w.write(indent + "    " + typeName + " operator()(const ::vespalib::slime::Inspector & __inspector, " + typeName + " __eDefault);\n");
                    w.write(indent + "};\n");
                } else {
                    w.write(indent + "class " + typeName + " {\n");
                    w.write(indent + "public:\n");
                    writeTypeDeclarations(w, child, indent + "    ");
                    writeStructFunctionDeclarations(w, getTypeName(child, false), child, indent + "    ");
                    writeMembers(w, child, indent + "    ");
                    w.write(indent + "};\n");
                    w.write(indent + "typedef std::vector<" + typeName + "> " + typeName + "Vector;\n\n");
                    w.write(indent + "typedef std::map<std::string, " + typeName + "> " + typeName + "Map;\n\n");
                }
            }
        }
    }
\n"
                + " * This class contains the config. DO NOT USE THIS CLASS DIRECTLY. Use the typedeffed\n"
                + " * versions after this class declaration.\n"
                + "
configgen/src/main/java/com/yahoo/config/codegen/CppClassBuilder.java