From ca9605215b31dccb946328fa315d8b6ca3fc9ce3 Mon Sep 17 00:00:00 2001 From: Kitzunu <24550914+Kitzunu@users.noreply.github.com> Date: Fri, 17 Sep 2021 14:51:01 +0200 Subject: [PATCH] feat(Core/Misc): improve enum flags with type safe operators (#7865) --- src/common/Utilities/EnumFlag.h | 119 ++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/common/Utilities/EnumFlag.h diff --git a/src/common/Utilities/EnumFlag.h b/src/common/Utilities/EnumFlag.h new file mode 100644 index 000000000..b9fc9168e --- /dev/null +++ b/src/common/Utilities/EnumFlag.h @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version. + * Copyright (C) 2008-2021 TrinityCore + */ + +#ifndef EnumFlag_h__ +#define EnumFlag_h__ + +#include + +template +constexpr bool IsEnumFlag(T) { return false; } + +#define DEFINE_ENUM_FLAG(enumType) constexpr bool IsEnumFlag(enumType) { return true; } + +namespace EnumTraits +{ + template + using IsFlag = std::integral_constant; +} + +template::value, std::nullptr_t> = nullptr> +inline constexpr T operator&(T left, T right) +{ + return static_cast(static_cast>(left) & static_cast>(right)); +} + +template::value, std::nullptr_t> = nullptr> +inline constexpr T& operator&=(T& left, T right) +{ + return left = left & right; +} + +template::value, std::nullptr_t> = nullptr> +inline constexpr T operator|(T left, T right) +{ + return static_cast(static_cast>(left) | static_cast>(right)); +} + +template::value, std::nullptr_t> = nullptr> +inline constexpr T& operator|=(T& left, T right) +{ + return left = left | right; +} + +template::value, std::nullptr_t> = nullptr> +inline constexpr T operator~(T value) +{ + return static_cast(~static_cast>(value)); +} + +template +class EnumFlag +{ + static_assert(EnumTraits::IsFlag::value, "EnumFlag must be used only with enums that are specify EnumFlag::IsFlag"); + +public: + /*implicit*/ constexpr EnumFlag(T value) : _value(value) + { + } + + constexpr EnumFlag& operator&=(EnumFlag right) + { + _value &= right._value; + return *this; + } + + constexpr friend EnumFlag operator&(EnumFlag left, EnumFlag right) + { + return left &= right; + } + + constexpr EnumFlag& operator|=(EnumFlag right) + { + _value |= right._value; + return *this; + } + + constexpr friend EnumFlag operator|(EnumFlag left, EnumFlag right) + { + return left |= right; + } + + constexpr EnumFlag operator~() const + { + return static_cast(~static_cast>(_value)); + } + + constexpr void RemoveFlag(EnumFlag flag) + { + _value &= ~flag._value; + } + + constexpr bool HasFlag(T flag) const + { + using i = std::underlying_type_t; + return static_cast(_value & flag) != static_cast(0); + } + + constexpr bool HasAllFlags(T flags) const + { + return (_value & flags) == flags; + } + + constexpr operator T() const + { + return _value; + } + + constexpr std::underlying_type_t AsUnderlyingType() const + { + return static_cast>(_value); + } + +private: + T _value; +}; + +#endif // EnumFlag_h__