From 1bb590a57ed9557bee2fc5bf4e1b85d770d208ed Mon Sep 17 00:00:00 2001 From: skypjack Date: Fri, 23 Jan 2026 18:01:16 +0100 Subject: [PATCH] enum: enum_bitmask concept --- src/entt/core/enum.hpp | 56 ++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/entt/core/enum.hpp b/src/entt/core/enum.hpp index 5922c2f8e..0f9c4f4a5 100644 --- a/src/entt/core/enum.hpp +++ b/src/entt/core/enum.hpp @@ -9,12 +9,16 @@ namespace entt { * @brief Enable bitmask support for enum classes. * @tparam Type The enum type for which to enable bitmask support. */ -template +template struct enum_as_bitmask: std::false_type {}; /*! @copydoc enum_as_bitmask */ template -struct enum_as_bitmask>: std::is_enum {}; +requires requires { + requires std::is_enum_v; + { Type::_entt_enum_as_bitmask } -> std::same_as; +} +struct enum_as_bitmask: std::true_type {}; /** * @brief Helper variable template. @@ -23,6 +27,14 @@ struct enum_as_bitmask> template inline constexpr bool enum_as_bitmask_v = enum_as_bitmask::value; +/** + * @brief Specify that an enum class supports bitmask operations. + * @tparam Type Enum class type. + */ +template +// check again that it is an enum to deal with incorrect specializations +concept enum_bitmask = std::is_enum_v && enum_as_bitmask_v; + } // namespace entt /** @@ -33,23 +45,20 @@ inline constexpr bool enum_as_bitmask_v = enum_as_bitmask::value; * @return The result of invoking the operator on the underlying types of the * two values provided. */ -template -[[nodiscard]] constexpr std::enable_if_t, Type> -operator|(const Type lhs, const Type rhs) noexcept { +template +[[nodiscard]] constexpr Type operator|(const Type lhs, const Type rhs) noexcept { return static_cast(static_cast>(lhs) | static_cast>(rhs)); } /*! @copydoc operator| */ -template -[[nodiscard]] constexpr std::enable_if_t, Type> -operator&(const Type lhs, const Type rhs) noexcept { +template +[[nodiscard]] constexpr Type operator&(const Type lhs, const Type rhs) noexcept { return static_cast(static_cast>(lhs) & static_cast>(rhs)); } /*! @copydoc operator| */ -template -[[nodiscard]] constexpr std::enable_if_t, Type> -operator^(const Type lhs, const Type rhs) noexcept { +template +[[nodiscard]] constexpr Type operator^(const Type lhs, const Type rhs) noexcept { return static_cast(static_cast>(lhs) ^ static_cast>(rhs)); } @@ -60,37 +69,32 @@ operator^(const Type lhs, const Type rhs) noexcept { * @return The result of invoking the operator on the underlying types of the * value provided. */ -template -[[nodiscard]] constexpr std::enable_if_t, Type> -operator~(const Type value) noexcept { +template +[[nodiscard]] constexpr Type operator~(const Type value) noexcept { return static_cast(~static_cast>(value)); } /*! @copydoc operator~ */ -template -[[nodiscard]] constexpr std::enable_if_t, bool> -operator!(const Type value) noexcept { +template +[[nodiscard]] constexpr bool operator!(const Type value) noexcept { return !static_cast>(value); } /*! @copydoc operator| */ -template -constexpr std::enable_if_t, Type &> -operator|=(Type &lhs, const Type rhs) noexcept { +template +constexpr Type &operator|=(Type &lhs, const Type rhs) noexcept { return (lhs = (lhs | rhs)); } /*! @copydoc operator| */ -template -constexpr std::enable_if_t, Type &> -operator&=(Type &lhs, const Type rhs) noexcept { +template +constexpr Type &operator&=(Type &lhs, const Type rhs) noexcept { return (lhs = (lhs & rhs)); } /*! @copydoc operator| */ -template -constexpr std::enable_if_t, Type &> -operator^=(Type &lhs, const Type rhs) noexcept { +template +constexpr Type &operator^=(Type &lhs, const Type rhs) noexcept { return (lhs = (lhs ^ rhs)); }