bug 899859 - Add typed enums support in strutures / classes - r=Waldo
authorGuillaume Abadie <gabadie@mozilla.com>
Fri, 02 Aug 2013 20:51:00 -0400
changeset 154441 646082ecc3a9858d89d1879a27b9b0c913bba3a5
parent 154440 e35b3cf5c8ddb3d5cf502e2c58a3d70969eeaa5c
child 154442 2fe371042c60ada23141447a10e4b180401d9e42
push id382
push userakeybl@mozilla.com
push dateMon, 21 Oct 2013 21:47:13 +0000
treeherdermozilla-release@5f1868ee45cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs899859
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 899859 - Add typed enums support in strutures / classes - r=Waldo
mfbt/TypedEnum.h
--- a/mfbt/TypedEnum.h
+++ b/mfbt/TypedEnum.h
@@ -87,26 +87,43 @@
  * fail.  In other compilers, Enum itself will actually be defined as a class,
  * and some implicit conversions will fail while others will succeed.
  *
  * The type argument specifies the underlying type for the enum where
  * supported, as with MOZ_ENUM_TYPE().  For simplicity, it is currently
  * mandatory.  As with MOZ_ENUM_TYPE(), it will do nothing on compilers that do
  * not support it.
  *
- * Note that the workaround implemented here is not compatible with enums
- * nested inside a class.
+ * MOZ_{BEGIN,END}_ENUM_CLASS doesn't work for defining enum classes nested
+ * inside classes.  To define an enum class nested inside another class, use
+ * MOZ_{BEGIN,END}_NESTED_ENUM_CLASS, and place a MOZ_FINISH_NESTED_ENUM_CLASS
+ * in namespace scope to handle bits that can only be implemented with
+ * namespace-scoped code.  For example:
+ *
+ *   class FooBar {
+ *
+ *     MOZ_BEGIN_NESTED_ENUM_CLASS(Enum, int32_t)
+ *       A,
+ *       B = 6
+ *     MOZ_END_NESTED_ENUM_CLASS(Enum)
+ *
+ *   };
+ *
+ *   MOZ_FINISH_NESTED_ENUM_CLASS(FooBar::Enum)
  */
 #if defined(MOZ_HAVE_CXX11_STRONG_ENUMS)
   /*
    * All compilers that support strong enums also support an explicit
    * underlying type, so no extra check is needed.
    */
-#  define MOZ_BEGIN_ENUM_CLASS(Name, type) enum class Name : type {
-#  define MOZ_END_ENUM_CLASS(Name)         };
+#  define MOZ_BEGIN_NESTED_ENUM_CLASS(Name, type) \
+     enum class Name : type {
+#  define MOZ_END_NESTED_ENUM_CLASS(Name) \
+     };
+#  define MOZ_FINISH_NESTED_ENUM_CLASS(Name) /* nothing */
 #else
    /**
     * We need Name to both name a type, and scope the provided enumerator
     * names.  Namespaces and classes both provide scoping, but namespaces
     * aren't types, so we need to use a class that wraps the enum values.  We
     * have an implicit conversion from the inner enum type to the class, so
     * statements like
     *
@@ -132,32 +149,33 @@
     * But we can't prevent things like this, because C++ doesn't allow
     * overriding conversions or assignment operators for enums:
     *
     *   int x = Enum::A;
     *   int f()
     *   {
     *     return Enum::A;
     *   }
-    */
-#  define MOZ_BEGIN_ENUM_CLASS(Name, type) \
+    */\
+#  define MOZ_BEGIN_NESTED_ENUM_CLASS(Name, type) \
      class Name \
      { \
        public: \
          enum Enum MOZ_ENUM_TYPE(type) \
          {
-#  define MOZ_END_ENUM_CLASS(Name) \
+#  define MOZ_END_NESTED_ENUM_CLASS(Name) \
          }; \
          Name() {} \
          Name(Enum aEnum) : mEnum(aEnum) {} \
          explicit Name(int num) : mEnum((Enum)num) {} \
          operator Enum() const { return mEnum; } \
        private: \
          Enum mEnum; \
-     }; \
+     };
+#  define MOZ_FINISH_NESTED_ENUM_CLASS(Name) \
      inline int operator+(const int&, const Name::Enum&) MOZ_DELETE; \
      inline int operator+(const Name::Enum&, const int&) MOZ_DELETE; \
      inline int operator-(const int&, const Name::Enum&) MOZ_DELETE; \
      inline int operator-(const Name::Enum&, const int&) MOZ_DELETE; \
      inline int operator*(const int&, const Name::Enum&) MOZ_DELETE; \
      inline int operator*(const Name::Enum&, const int&) MOZ_DELETE; \
      inline int operator/(const int&, const Name::Enum&) MOZ_DELETE; \
      inline int operator/(const Name::Enum&, const int&) MOZ_DELETE; \
@@ -203,12 +221,16 @@
      inline int& operator/=(int&, const Name::Enum&) MOZ_DELETE; \
      inline int& operator%=(int&, const Name::Enum&) MOZ_DELETE; \
      inline int& operator&=(int&, const Name::Enum&) MOZ_DELETE; \
      inline int& operator|=(int&, const Name::Enum&) MOZ_DELETE; \
      inline int& operator^=(int&, const Name::Enum&) MOZ_DELETE; \
      inline int& operator<<=(int&, const Name::Enum&) MOZ_DELETE; \
      inline int& operator>>=(int&, const Name::Enum&) MOZ_DELETE;
 #endif
+#  define MOZ_BEGIN_ENUM_CLASS(Name, type) MOZ_BEGIN_NESTED_ENUM_CLASS(Name, type)
+#  define MOZ_END_ENUM_CLASS(Name) \
+     MOZ_END_NESTED_ENUM_CLASS(Name) \
+     MOZ_FINISH_NESTED_ENUM_CLASS(Name)
 
 #endif /* __cplusplus */
 
 #endif /* mozilla_TypedEnum_h */