diff --git a/CMakeLists.txt b/CMakeLists.txt index 15ddc13..320e558 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ set(HEADER_FILES io/path.h io/nativefilestream.h io/misc.h + misc/flagenumclass.h misc/math.h misc/multiarray.h misc/parseerror.h diff --git a/misc/flagenumclass.h b/misc/flagenumclass.h new file mode 100644 index 0000000..7876ba5 --- /dev/null +++ b/misc/flagenumclass.h @@ -0,0 +1,79 @@ +#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 \tp T. + * \remarks This class is still experimental and might be changed or removed in future minior releases. + */ +template struct IsFlagEnumClass : public Traits::Bool { +}; + +/*! + * \def The 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-=; \ + } + +/*! + * \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 + +} // namespace CppUtilities + +#endif // CPP_UTILITIES_FLAG_ENUM_CLASS_H