Implemented option --scoped-enum for C++ generator
authorvijairaj <vijairaj.r@gmail.com>
Tue, 15 Sep 2015 08:11:29 +0000 (13:41 +0530)
committervijairaj <vijairaj.r@gmail.com>
Tue, 15 Sep 2015 10:43:52 +0000 (16:13 +0530)
This generates C++11 style scoped and strongly typed enums.
Enabling this option also implies --no-prefix.

docs/html/md__compiler.html
docs/source/Compiler.md
include/flatbuffers/idl.h
src/flatc.cpp
src/idl_gen_cpp.cpp

index 043cb23..6ae87ed 100644 (file)
@@ -78,6 +78,7 @@ $(document).ready(function(){initNavTree('md__compiler.html','');});
 <li><code>--strict-json</code> : Require &amp; generate strict JSON (field names are enclosed in quotes, no trailing commas in tables/vectors). By default, no quotes are required/generated, and trailing commas are allowed.</li>
 <li><code>--defaults-json</code> : Output fields whose value is equal to the default value when writing JSON text.</li>
 <li><code>--no-prefix</code> : Don't prefix enum values in generated C++ by their enum type.</li>
+<li><code>--scoped-enums</code> : Use C++11 style scoped and strongly typed enums in generated C++. This also implies <code>--no-prefix</code>.</li>
 <li><code>--gen-includes</code> : (deprecated), this is the default behavior. If the original behavior is required (no include statements) use <code>--no-includes.</code></li>
 <li><code>--no-includes</code> : Don't generate include statements for included schemas the generated file depends on (C++).</li>
 <li><code>--gen-mutable</code> : Generate additional non-const accessors for mutating FlatBuffers in-place.</li>
index 5d254df..e4663e1 100755 (executable)
@@ -51,6 +51,9 @@ be generated for each file processed:
 -   `--no-prefix` : Don't prefix enum values in generated C++ by their enum
     type.
 
+-   `--scoped-enums` : Use C++11 style scoped and strongly typed enums in
+    generated C++. This also implies `--no-prefix`.
+
 -   `--gen-includes` : (deprecated), this is the default behavior.
                        If the original behavior is required (no include
                           statements) use `--no-includes.`
index 8a912de..44154eb 100644 (file)
@@ -425,6 +425,7 @@ struct GeneratorOptions {
   int indent_step;
   bool output_enum_identifiers;
   bool prefixed_enums;
+  bool scoped_enums;
   bool include_dependence_headers;
   bool mutable_buffer;
   bool one_file;
@@ -437,7 +438,7 @@ struct GeneratorOptions {
   GeneratorOptions() : strict_json(false),
                        output_default_scalars_in_json(false),
                        indent_step(2),
-                       output_enum_identifiers(true), prefixed_enums(true),
+                       output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false),
                        include_dependence_headers(true),
                        mutable_buffer(false),
                        one_file(false),
index 9b8b50d..7f654b0 100644 (file)
@@ -90,6 +90,8 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) {
       "  --defaults-json Output fields whose value is the default when\n"
       "                  writing JSON\n"
       "  --no-prefix     Don\'t prefix enum values with the enum type in C++.\n"
+      "  --scoped-enums  Use C++11 style scoped and strongly typed enums.\n"
+      "                  also implies --no-prefix.\n"
       "  --gen-includes  (deprecated), this is the default behavior.\n"
       "                  If the original behavior is required (no include\n"
          "                  statements) use --no-includes.\n"
@@ -142,6 +144,9 @@ int main(int argc, const char *argv[]) {
         opts.output_default_scalars_in_json = true;
       } else if(arg == "--no-prefix") {
         opts.prefixed_enums = false;
+      } else if(arg == "--scoped-enums") {
+        opts.prefixed_enums = false;
+        opts.scoped_enums = true;
       } else if(arg == "--gen-mutable") {
         opts.mutable_buffer = true;
       } else if(arg == "--gen-includes") {
index 2cb15b5..acdc630 100644 (file)
@@ -124,12 +124,28 @@ static std::string GenTypeGet(const Parser &parser, const Type &type,
     : beforeptr + GenTypePointer(parser, type) + afterptr;
 }
 
+static std::string GenEnumDecl(const EnumDef &enum_def,
+                               const GeneratorOptions &opts) {
+  return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name;
+}
+
 static std::string GenEnumVal(const EnumDef &enum_def, const EnumVal &enum_val,
                               const GeneratorOptions &opts) {
   return opts.prefixed_enums ? enum_def.name + "_" + enum_val.name
                              : enum_val.name;
 }
 
+static std::string GetEnumVal(const EnumDef &enum_def, const EnumVal &enum_val,
+                              const GeneratorOptions &opts) {
+  if (opts.scoped_enums) {
+      return enum_def.name + "::" + enum_val.name;
+  } else if (opts.prefixed_enums) {
+      return enum_def.name + "_" + enum_val.name;
+  } else {
+      return enum_val.name;
+  }
+}
+
 // Generate an enum declaration and an enum string lookup table.
 static void GenEnum(const Parser &parser, EnumDef &enum_def,
                     std::string *code_ptr, std::string *code_ptr_post,
@@ -138,7 +154,7 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def,
   std::string &code = *code_ptr;
   std::string &code_post = *code_ptr_post;
   GenComment(enum_def.doc_comment, code_ptr, nullptr);
-  code += "enum " + enum_def.name + " {\n";
+  code += GenEnumDecl(enum_def, opts) + " {\n";
   for (auto it = enum_def.vals.vec.begin();
        it != enum_def.vals.vec.end();
        ++it) {
@@ -171,9 +187,9 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def,
     }
     code += "nullptr };\n  return names;\n}\n\n";
     code += "inline const char *EnumName" + enum_def.name;
-    code += "(" + enum_def.name + " e) { return EnumNames" + enum_def.name + "()[e";
+    code += "(" + enum_def.name + " e) { return EnumNames" + enum_def.name + "()[static_cast<int>(e)";
     if (enum_def.vals.vec.front()->value)
-      code += " - " + GenEnumVal(enum_def, *enum_def.vals.vec.front(), opts);
+      code += " - static_cast<int>(" + GetEnumVal(enum_def, *enum_def.vals.vec.front(), opts) +")";
     code += "]; }\n\n";
   }
 
@@ -192,7 +208,7 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def,
          it != enum_def.vals.vec.end();
          ++it) {
       auto &ev = **it;
-      code_post += "    case " + GenEnumVal(enum_def, ev, opts);
+      code_post += "    case " + GetEnumVal(enum_def, ev, opts);
       if (!ev.value) {
         code_post += ": return true;\n";  // "NONE" enum value.
       } else {
@@ -425,7 +441,7 @@ static void GenTable(const Parser &parser, StructDef &struct_def,
         if (ev) {
           code += WrapInNameSpace(parser,
                                   field.value.type.enum_def->defined_namespace,
-                                  GenEnumVal(*field.value.type.enum_def, *ev,
+                                  GetEnumVal(*field.value.type.enum_def, *ev,
                                              opts));
         } else {
           code += GenUnderlyingCast(parser, field, true, field.value.constant);