diff --git a/include/Nazara/Core/Flags.hpp b/include/Nazara/Core/Flags.hpp index 36ff02f6b..e87d21158 100644 --- a/include/Nazara/Core/Flags.hpp +++ b/include/Nazara/Core/Flags.hpp @@ -18,17 +18,22 @@ namespace Nz { }; - // From: https://stackoverflow.com/questions/11927032/sfinae-check-for-static-member-using-decltype - template - class IsEnumFlag + template + struct IsEnumFlag : std::false_type {}; + + template + struct IsEnumFlag::max)>> : std::true_type {}; + + template + struct GetEnumAutoFlag : std::false_type { - template::max)>::value>::type> - static std::true_type check(int); + static constexpr bool value = true; + }; - template static std::false_type check(...); - - public: - static constexpr bool value = decltype(check(0))::value; + template + struct GetEnumAutoFlag> : std::true_type + { + static constexpr bool value = T::AutoFlag; }; template @@ -36,8 +41,10 @@ namespace Nz { static_assert(std::is_enum::value, "Type must be an enumeration"); static_assert(IsEnumFlag::value, "Enum has not been enabled as flags by an EnumAsFlags specialization"); + static_assert(std::is_same_v::max)>, E>, "EnumAsFlags field max should be of the same type as the enum"); static constexpr std::size_t MaxValue = static_cast(EnumAsFlags::max); + static constexpr bool AutoFlag = GetEnumAutoFlag::value; using BitField16 = std::conditional_t<(MaxValue >= 8), UInt16, UInt8>; using BitField32 = std::conditional_t<(MaxValue >= 16), UInt32, BitField16>; diff --git a/include/Nazara/Core/Flags.inl b/include/Nazara/Core/Flags.inl index 36a001c4f..cb51a277a 100644 --- a/include/Nazara/Core/Flags.inl +++ b/include/Nazara/Core/Flags.inl @@ -258,7 +258,10 @@ namespace Nz template constexpr typename Flags::BitField Flags::GetFlagValue(E enumValue) { - return 1U << static_cast(enumValue); + if constexpr (AutoFlag) + return 1U << static_cast(enumValue); + else + return enumValue; } /*!