Add helper to ease creation of flag enums

Not sure whether this is the best way, especially the regarding
the namespacing - hence still experimental
This commit is contained in:
Martchus 2019-08-12 20:20:55 +02:00
parent f9bd0b5987
commit e8d829cadd
2 changed files with 80 additions and 0 deletions

View File

@ -26,6 +26,7 @@ set(HEADER_FILES
io/path.h io/path.h
io/nativefilestream.h io/nativefilestream.h
io/misc.h io/misc.h
misc/flagenumclass.h
misc/math.h misc/math.h
misc/multiarray.h misc/multiarray.h
misc/parseerror.h misc/parseerror.h

79
misc/flagenumclass.h Normal file
View File

@ -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 <typename T> struct IsFlagEnumClass : public Traits::Bool<false> {
};
/*!
* \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<EnumClassType> : Traits::Bool<true> { \
}; \
} \
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 <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass operator|(FlagEnumClass lhs, FlagEnumClass rhs)
{
return static_cast<FlagEnumClass>(
static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs) | static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs));
}
template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr bool operator&(FlagEnumClass lhs, FlagEnumClass rhs)
{
return static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs)
& static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs);
}
template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass &operator|=(FlagEnumClass &lhs, FlagEnumClass rhs)
{
return lhs = static_cast<FlagEnumClass>(static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs)
| static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs));
}
template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass &operator+=(FlagEnumClass &lhs, FlagEnumClass rhs)
{
return lhs = static_cast<FlagEnumClass>(static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs)
| static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs));
}
template <typename FlagEnumClass, Traits::EnableIf<IsFlagEnumClass<FlagEnumClass>> * = nullptr>
constexpr FlagEnumClass &operator-=(FlagEnumClass &lhs, FlagEnumClass rhs)
{
return lhs = static_cast<FlagEnumClass>(static_cast<typename std::underlying_type<FlagEnumClass>::type>(lhs)
& (~static_cast<typename std::underlying_type<FlagEnumClass>::type>(rhs)));
}
} // namespace FlagEnumClassOperations
} // namespace CppUtilities
#endif // CPP_UTILITIES_FLAG_ENUM_CLASS_H