chore: make FlagsEnum constexpr (#5510)

This commit is contained in:
nerix
2024-07-16 16:35:44 +02:00
committed by GitHub
parent 6b73bb53ec
commit deb4401036
6 changed files with 425 additions and 46 deletions
+75 -44
View File
@@ -1,59 +1,74 @@
#pragma once
#include <initializer_list>
#include <concepts>
#include <type_traits>
namespace chatterino {
template <typename T, typename Q = typename std::underlying_type<T>::type>
template <typename T>
requires std::is_enum_v<T>
class FlagsEnum
{
public:
FlagsEnum()
: value_(static_cast<T>(0))
using Int = std::underlying_type_t<T>;
constexpr FlagsEnum() noexcept = default;
constexpr FlagsEnum(std::convertible_to<T> auto... flags) noexcept
: value_(
static_cast<T>((static_cast<Int>(static_cast<T>(flags)) | ...)))
{
}
FlagsEnum(T value)
: value_(value)
friend constexpr bool operator==(FlagsEnum lhs, FlagsEnum rhs) noexcept
{
return lhs.value_ == rhs.value_;
}
friend constexpr bool operator!=(FlagsEnum lhs, FlagsEnum rhs) noexcept
{
return lhs.value_ != rhs.value_;
}
FlagsEnum(std::initializer_list<T> flags)
friend constexpr bool operator==(FlagsEnum lhs, T rhs) noexcept
{
for (auto flag : flags)
{
this->set(flag);
}
return lhs.value_ == rhs;
}
friend constexpr bool operator!=(FlagsEnum lhs, T rhs) noexcept
{
return lhs.value_ != rhs;
}
bool operator==(const FlagsEnum<T> &other) const
friend constexpr bool operator==(T lhs, FlagsEnum rhs) noexcept
{
return this->value_ == other.value_;
return lhs == rhs.value_;
}
friend constexpr bool operator!=(T lhs, FlagsEnum rhs) noexcept
{
return lhs != rhs.value_;
}
bool operator!=(const FlagsEnum<T> &other) const
constexpr void set(std::convertible_to<T> auto... flags) noexcept
{
return this->value_ != other.value_;
}
void set(T flag)
{
reinterpret_cast<Q &>(this->value_) |= static_cast<Q>(flag);
this->value_ =
static_cast<T>(static_cast<Int>(this->value_) |
(static_cast<Int>(static_cast<T>(flags)) | ...));
}
/** Adds the flags from `flags` in this enum. */
void set(FlagsEnum flags)
constexpr void set(FlagsEnum flags) noexcept
{
reinterpret_cast<Q &>(this->value_) |= static_cast<Q>(flags.value_);
this->value_ = static_cast<T>(static_cast<Int>(this->value_) |
static_cast<Int>(flags.value_));
}
void unset(T flag)
constexpr void unset(std::convertible_to<T> auto... flags) noexcept
{
reinterpret_cast<Q &>(this->value_) &= ~static_cast<Q>(flag);
this->value_ =
static_cast<T>(static_cast<Int>(this->value_) &
~(static_cast<Int>(static_cast<T>(flags)) | ...));
}
void set(T flag, bool value)
constexpr void set(T flag, bool value) noexcept
{
if (value)
{
@@ -65,43 +80,59 @@ public:
}
}
bool has(T flag) const
constexpr FlagsEnum operator|(T flag) const noexcept
{
return static_cast<Q>(this->value_) & static_cast<Q>(flag);
return static_cast<T>(static_cast<Int>(this->value_) |
static_cast<Int>(flag));
}
FlagsEnum operator|(T flag)
constexpr FlagsEnum operator|(FlagsEnum rhs) const noexcept
{
FlagsEnum xd;
xd.value_ = this->value_;
xd.set(flag, true);
return xd;
return static_cast<T>(static_cast<Int>(this->value_) |
static_cast<Int>(rhs.value_));
}
FlagsEnum operator|(FlagsEnum rhs)
constexpr bool has(T flag) const noexcept
{
return static_cast<T>(static_cast<Q>(this->value_) |
static_cast<Q>(rhs.value_));
return static_cast<Int>(this->value_) & static_cast<Int>(flag);
}
bool hasAny(FlagsEnum flags) const
constexpr bool hasAny(FlagsEnum flags) const noexcept
{
return static_cast<Q>(this->value_) & static_cast<Q>(flags.value_);
return (static_cast<Int>(this->value_) &
static_cast<Int>(flags.value_)) != 0;
}
bool hasAll(FlagsEnum<T> flags) const
constexpr bool hasAny(std::convertible_to<T> auto... flags) const noexcept
{
return (static_cast<Q>(this->value_) & static_cast<Q>(flags.value_)) &&
static_cast<Q>(flags->value);
return this->hasAny(FlagsEnum{flags...});
}
bool hasNone(std::initializer_list<T> flags) const
constexpr bool hasAll(FlagsEnum flags) const noexcept
{
return !this->hasAny(flags);
return (static_cast<Int>(this->value_) &
static_cast<Int>(flags.value_)) ==
static_cast<Int>(flags.value_);
}
T value() const
constexpr bool hasAll(std::convertible_to<T> auto... flags) const noexcept
{
return this->hasAll(FlagsEnum{flags...});
}
constexpr bool hasNone(FlagsEnum flags) const noexcept
{
return (static_cast<Int>(this->value_) &
static_cast<Int>(flags.value_)) == 0;
}
constexpr bool hasNone() const noexcept = delete;
constexpr bool hasNone(std::convertible_to<T> auto... flags) const noexcept
{
return this->hasNone(FlagsEnum{flags...});
}
constexpr T value() const noexcept
{
return this->value_;
}