#ifndef CPP_UTILITIES_FLAG_ENUM_CLASS_H #define CPP_UTILITIES_FLAG_ENUM_CLASS_H #include "./traits.h" namespace CppUtilities { /*! * \brief The IsFlagEnumClass class is used to decide whether to enable operations for flag enums for \tparam T. * \remarks This class is still experimental and might be changed or removed in future minior releases. */ template struct IsFlagEnumClass : public Traits::Bool {}; // clang-format off /*! * \brief The \def CPP_UTILITIES_MARK_FLAG_ENUM_CLASS macro enables flag enum operators for \a EnumClassType within namespace \a Namespace. * \remarks * - Must be used outside a namespace. * - This macro is still experimental and might be changed or removed in future minior releases. */ #define CPP_UTILITIES_MARK_FLAG_ENUM_CLASS(Namespace, EnumClassType) \ namespace CppUtilities { \ template <> struct IsFlagEnumClass : Traits::Bool { \ }; \ } \ namespace Namespace { \ using CppUtilities::FlagEnumClassOperations::operator|; \ using CppUtilities::FlagEnumClassOperations::operator&; \ using CppUtilities::FlagEnumClassOperations::operator|=; \ using CppUtilities::FlagEnumClassOperations::operator+=; \ using CppUtilities::FlagEnumClassOperations::operator-=; \ } // clang-format on /*! * \brief The FlagEnumClassOperations namespace contains operations for flag enums. * \remarks This namespace is still experimental and might be changed or removed in future minior releases. */ namespace FlagEnumClassOperations { template > * = nullptr> constexpr FlagEnumClass operator|(FlagEnumClass lhs, FlagEnumClass rhs) { return static_cast( static_cast::type>(lhs) | static_cast::type>(rhs)); } template > * = nullptr> constexpr bool operator&(FlagEnumClass lhs, FlagEnumClass rhs) { return static_cast::type>(lhs) & static_cast::type>(rhs); } template > * = nullptr> constexpr FlagEnumClass &operator|=(FlagEnumClass &lhs, FlagEnumClass rhs) { return lhs = static_cast(static_cast::type>(lhs) | static_cast::type>(rhs)); } template > * = nullptr> constexpr FlagEnumClass &operator+=(FlagEnumClass &lhs, FlagEnumClass rhs) { return lhs = static_cast(static_cast::type>(lhs) | static_cast::type>(rhs)); } template > * = nullptr> constexpr FlagEnumClass &operator-=(FlagEnumClass &lhs, FlagEnumClass rhs) { return lhs = static_cast(static_cast::type>(lhs) & (~static_cast::type>(rhs))); } } // namespace FlagEnumClassOperations /*! * \brief Sets the specified \a relevantFlags in the specified \a flagVariable to the specified \a value. */ template > * = nullptr> constexpr FlagEnumClass &modFlagEnum(FlagEnumClass &flagVariable, FlagEnumClass relevantFlags, bool value) { return value ? (flagVariable += relevantFlags) : (flagVariable -= relevantFlags); } /*! * \brief Returns whether the specified \a flagVariable has set all flags specified via \a flagsToCheck to true. */ template > * = nullptr> constexpr bool checkFlagEnum(FlagEnumClass flagVariable, FlagEnumClass flagsToCheck) { return (static_cast::type>(flagVariable) & static_cast::type>(flagsToCheck)) == static_cast::type>(flagsToCheck); } } // namespace CppUtilities #endif // CPP_UTILITIES_FLAG_ENUM_CLASS_H