From 1cfe53e8279ba76a4c505b61c07474de9de37c07 Mon Sep 17 00:00:00 2001 From: Anton Bachin Date: Mon, 18 May 2015 00:53:00 -0500 Subject: [PATCH] Option to opt in to implicit conversion to enum class instead of enum. A Better Enum is normally implicitly convertible to its internal enum type, which makes it then implicitly convertible to an integer as well. The former conversion is necessary for Better Enums to be usable in switch statements. This change makes it possible to define BETTER_ENUMS_SAFER_SWITCH, which makes Better Enums convert to an enum class, preventing the implicit conversion to integers. The drawback is that switch cases have to be written as case Enum::_Case::A: instead of case Enum::A: --- enum.h | 27 ++++++++++++++++++++------- pp_map_gen.py | 4 ++-- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/enum.h b/enum.h index 1366e4b..0d8cf0b 100644 --- a/enum.h +++ b/enum.h @@ -3,8 +3,8 @@ #pragma once -#ifndef _BETTER_ENUM_ENUM_H_ -#define _BETTER_ENUM_ENUM_H_ +#ifndef _BETTER_ENUMS_ENUM_H_ +#define _BETTER_ENUMS_ENUM_H_ @@ -14,9 +14,9 @@ -#ifdef BETTER_ENUM_PP_MAP_FILE +#ifdef BETTER_ENUMS_MACRO_FILE -#include BETTER_ENUM_PP_MAP_FILE +#include BETTER_ENUMS_MACRO_FILE #else @@ -331,7 +331,7 @@ X(f, l, 16) X(f, l, 17) X(f, l, 18) X(f, l, 19) X(f, l, 20) X(f, l, 21) \ X(f, l, 22) X(f, l, 23) -#endif // #ifdef BETTER_ENUM_PP_MAP_FILE +#endif // #ifdef BETTER_ENUMS_MACRO_FILE @@ -590,6 +590,19 @@ constexpr const _Iterable _names{_name_array, _size}; \ #define _ENUM_NS(EnumType) _enum::_data_ ## EnumType #define _ENUM_NOT_FOUND ((size_t)-1) +#ifndef BETTER_ENUMS_SAFER_SWITCH + +#define _ENUM_CONVERSION_FOR_SWITCH(Integral, ...) \ + constexpr operator _Enumerated() const { return _value; } + +#else + +#define _ENUM_CONVERSION_FOR_SWITCH(Integral, ...) \ + enum class _Case : Integral { __VA_ARGS__ }; \ + constexpr operator _Case() const { return (_Case)_value; } + +#endif // #ifndef BETTER_ENUMS_SAFER_SWITCH + #define _ENUM_TYPE(EnumType, Integral, ...) \ class EnumType : public _ENUM_NS(EnumType)::_Base { \ protected: \ @@ -658,7 +671,7 @@ class EnumType : public _ENUM_NS(EnumType)::_Base { \ return _from_string_nocase_loop(name, false) != _ENUM_NOT_FOUND; \ } \ \ - constexpr operator _Enumerated() const { return _value; } \ + _ENUM_CONVERSION_FOR_SWITCH(Integral, __VA_ARGS__); \ \ constexpr static auto &_values = _ENUM_NS(EnumType)::_values; \ constexpr static auto &_names = _ENUM_NS(EnumType)::_names; \ @@ -721,4 +734,4 @@ constexpr const EnumType operator +(_ENUM_NS(EnumType)::_Base base) \ -#endif // #ifndef _BETTER_ENUM_ENUM_H_ +#endif // #ifndef _BETTER_ENUMS_ENUM_H_ diff --git a/pp_map_gen.py b/pp_map_gen.py index 02b952e..2d71726 100755 --- a/pp_map_gen.py +++ b/pp_map_gen.py @@ -25,8 +25,8 @@ # somewhere in your include path. # 1. Run python pp_map_gen.py 512 128 > MACRO_FILE # 2. Build your code with an additional compiler flag: -# - for gcc and clang, -DBETTER_ENUM_PP_MAP_FILE='' -# - for VC++, /DBETTER_ENUM_PP_MAP_FILE='' +# - for gcc and clang, -BETTER_ENUMS_MACRO_FILE='' +# - for VC++, /BETTER_ENUMS_MACRO_FILE='' # or use any other method of getting these macros declared. # 3. Compile your code. Your macro file should be included, and enum.h should # happily work with whatever limits you chose.