From 6278793a0b55866325216c65249086e727bd9359 Mon Sep 17 00:00:00 2001 From: Anton Bachin Date: Tue, 7 Jul 2015 11:06:04 -0500 Subject: [PATCH] Added workarounds for VC2008. VC2008 has two quirks. It generates linking errors if a copy constructor is not explicitly defined on a Better Enum, and it has a buggy interaction between the ternary operator and throw. This change detects VC2008 and generates alternative code for that compiler. Having an explicitly-defined copy constructor in a literal type appears to cause an internal compiler error in g++4.7, and causes a spurious compilation failure in g++4.8. For this reason, the copy constructor generation is conditioned on the compiler. The replacement code for the ternary operator is also generated conditionally, because it uses an if-statement. The normal code has to compile in a constexpr context, and so has to use the ternary operator instead of the if-statement. Resolves #6. --- enum.h | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/enum.h b/enum.h index b0af2b2..5db25e5 100644 --- a/enum.h +++ b/enum.h @@ -54,6 +54,9 @@ # ifndef _CPPUNWIND # define BETTER_ENUMS__NO_EXCEPTIONS # endif +# if _MSC_VER < 1600 +# define BETTER_ENUMS__VC2008_WORKAROUNDS +# endif #endif #ifdef BETTER_ENUMS_CONSTEXPR @@ -315,12 +318,27 @@ _map_index(const Element *array, optional index) return index ? (CastTo)array[*index] : optional(); } +#ifdef BETTER_ENUMS__VC2008_WORKAROUNDS + +#define BETTER_ENUMS__OR_THROW \ + if (!maybe) \ + throw std::runtime_error(message); \ + \ + return *maybe; + +#else + +#define BETTER_ENUMS__OR_THROW \ + return maybe ? *maybe : throw std::runtime_error(message); + +#endif + BETTER_ENUMS__IF_EXCEPTIONS( template BETTER_ENUMS__CONSTEXPR static T _or_throw(optional maybe, const char *message) { - return maybe ? *maybe : throw std::runtime_error(message); + BETTER_ENUMS__OR_THROW } ) @@ -609,6 +627,18 @@ constexpr const char *_final_ ## index = \ #define BETTER_ENUMS__NS(EnumType) better_enums::_data_ ## EnumType +#ifdef BETTER_ENUMS__VC2008_WORKAROUNDS + +#define BETTER_ENUMS__COPY_CONSTRUCTOR(Enum) \ + BETTER_ENUMS__CONSTEXPR Enum(const Enum &other) : \ + _value(other._value) { } + +#else + +#define BETTER_ENUMS__COPY_CONSTRUCTOR(Enum) + +#endif + #define BETTER_ENUMS__TYPE(SetUnderlyingType, SwitchType, GenerateSwitchType, \ GenerateStrings, ToStringConstexpr, \ DeclareInitialize, DefineInitialize, CallInitialize,\ @@ -637,6 +667,8 @@ class Enum { \ BETTER_ENUMS__CONSTEXPR Enum(_enumerated value) : \ _value(_mapping::from_integral(value)) { } \ \ + BETTER_ENUMS__COPY_CONSTRUCTOR(Enum) \ + \ BETTER_ENUMS__CONSTEXPR operator SwitchType(Enum)() const \ { \ return (SwitchType(Enum))_mapping::to_integral(_value); \