Add GrTFlagsMask<> wrapper for C++11 bitfield enums

Previously, operator& for enum class bitfields was reserved only to
return a bool. e.g:

  if (flags & Flags::kFlag)

This change adds a new template class GrTFlagsMask<> that gets
instantiated by operator~ and allows us to write expressions like:

  flags &= ~Flags::kFlag
  (flags & ~Flags::kFlag1) | Flags::kFlag2

BUG=skia:

Change-Id: I21e5eb9304135e82cdda459e8a833a3489f6beaf
Reviewed-on: https://skia-review.googlesource.com/8563
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
csmartdalton 2017-02-19 23:51:45 -07:00 committed by Skia Commit-Bot
parent a9d0d9e71a
commit ad2a2becb6

View File

@ -53,25 +53,75 @@
template <typename T> \
friend X operator &(X a, T b); \
/**
* Wraps a C++11 enum that we use as a bitfield, and enables a limited amount of
* masking with type safety. Instantiated with the ~ operator.
*/
template<typename TFlags> class GrTFlagsMask {
public:
constexpr explicit GrTFlagsMask(TFlags value) : GrTFlagsMask(static_cast<int>(value)) {}
constexpr explicit GrTFlagsMask(int value) : fValue(value) {}
constexpr int value() const { return fValue; }
private:
const int fValue;
};
// Or-ing a mask always returns another mask.
template<typename TFlags> constexpr GrTFlagsMask<TFlags> operator|(GrTFlagsMask<TFlags> a,
GrTFlagsMask<TFlags> b) {
return GrTFlagsMask<TFlags>(a.value() | b.value());
}
template<typename TFlags> constexpr GrTFlagsMask<TFlags> operator|(GrTFlagsMask<TFlags> a,
TFlags b) {
return GrTFlagsMask<TFlags>(a.value() | static_cast<int>(b));
}
template<typename TFlags> constexpr GrTFlagsMask<TFlags> operator|(TFlags a,
GrTFlagsMask<TFlags> b) {
return GrTFlagsMask<TFlags>(static_cast<int>(a) | b.value());
}
template<typename TFlags> inline GrTFlagsMask<TFlags>& operator|=(GrTFlagsMask<TFlags>& a,
GrTFlagsMask<TFlags> b) {
return (a = a | b);
}
// And-ing two masks returns another mask; and-ing one with regular flags returns flags.
template<typename TFlags> constexpr GrTFlagsMask<TFlags> operator&(GrTFlagsMask<TFlags> a,
GrTFlagsMask<TFlags> b) {
return GrTFlagsMask<TFlags>(a.value() & b.value());
}
template<typename TFlags> constexpr TFlags operator&(GrTFlagsMask<TFlags> a, TFlags b) {
return static_cast<TFlags>(a.value() & static_cast<int>(b));
}
template<typename TFlags> constexpr TFlags operator&(TFlags a, GrTFlagsMask<TFlags> b) {
return static_cast<TFlags>(static_cast<int>(a) & b.value());
}
template<typename TFlags> inline TFlags& operator&=(TFlags& a, GrTFlagsMask<TFlags> b) {
return (a = a & b);
}
/**
* Defines bitwise operators that make it possible to use an enum class as a
* very basic bitfield.
* basic bitfield.
*/
#define GR_MAKE_BITFIELD_CLASS_OPS(X) \
inline X operator |(X a, X b) { \
return (X) ((int)a | (int)b); \
constexpr GrTFlagsMask<X> operator~(X a) { \
return GrTFlagsMask<X>(~static_cast<int>(a)); \
} \
inline X& operator |=(X& a, X b) { \
constexpr X operator|(X a, X b) { \
return static_cast<X>(static_cast<int>(a) | static_cast<int>(b)); \
} \
inline X& operator|=(X& a, X b) { \
return (a = a | b); \
} \
inline bool operator &(X a, X b) { \
return SkToBool((int)a & (int)b); \
}
constexpr bool operator&(X a, X b) { \
return SkToBool(static_cast<int>(a) & static_cast<int>(b)); \
} \
#define GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(X) \
friend X operator |(X a, X b); \
friend X& operator |=(X& a, X b); \
friend bool operator &(X a, X b);
friend constexpr GrTFlagsMask<X> operator ~(X); \
friend constexpr X operator |(X, X); \
friend X& operator |=(X&, X); \
friend constexpr bool operator &(X, X);
////////////////////////////////////////////////////////////////////////////////