Fix typo in 9b54bd30006c008b4a951331b273613d5bac3abf
[pm.git] / mfbt / TypedEnumBits.h
blob8f11b8d6fef641081c09451e593c52dc0a88f42d
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /*
8 * MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS allows using a typed enum as bit flags.
9 */
11 #ifndef mozilla_TypedEnumBits_h
12 #define mozilla_TypedEnumBits_h
14 #include "mozilla/Attributes.h"
15 #include "mozilla/IntegerTypeTraits.h"
17 namespace mozilla {
20 * The problem that CastableTypedEnumResult aims to solve is that
21 * typed enums are not convertible to bool, and there is no way to make them
22 * be, yet user code wants to be able to write
24 * if (myFlags & Flags::SOME_PARTICULAR_FLAG) (1)
26 * There are different approaches to solving this. Most of them require
27 * adapting user code. For example, we could implement operator! and have
28 * the user write
30 * if (!!(myFlags & Flags::SOME_PARTICULAR_FLAG)) (2)
32 * Or we could supply a IsNonZero() or Any() function returning whether
33 * an enum value is nonzero, and have the user write
35 * if (Any(Flags & Flags::SOME_PARTICULAR_FLAG)) (3)
37 * But instead, we choose to preserve the original user syntax (1) as it
38 * is inherently more readable, and to ease porting existing code to typed
39 * enums. We achieve this by having operator& and other binary bitwise
40 * operators have as return type a class, CastableTypedEnumResult,
41 * that wraps a typed enum but adds bool convertibility.
43 template<typename E>
44 class CastableTypedEnumResult
46 private:
47 const E mValue;
49 public:
50 explicit MOZ_CONSTEXPR CastableTypedEnumResult(E aValue)
51 : mValue(aValue)
54 MOZ_CONSTEXPR operator E() const { return mValue; }
56 template<typename DestinationType>
57 MOZ_EXPLICIT_CONVERSION MOZ_CONSTEXPR
58 operator DestinationType() const { return DestinationType(mValue); }
60 MOZ_CONSTEXPR bool operator !() const { return !bool(mValue); }
63 #define MOZ_CASTABLETYPEDENUMRESULT_BINOP(Op, OtherType, ReturnType) \
64 template<typename E> \
65 MOZ_CONSTEXPR ReturnType \
66 operator Op(const OtherType& aE, const CastableTypedEnumResult<E>& aR) \
67 { \
68 return ReturnType(aE Op OtherType(aR)); \
69 } \
70 template<typename E> \
71 MOZ_CONSTEXPR ReturnType \
72 operator Op(const CastableTypedEnumResult<E>& aR, const OtherType& aE) \
73 { \
74 return ReturnType(OtherType(aR) Op aE); \
75 } \
76 template<typename E> \
77 MOZ_CONSTEXPR ReturnType \
78 operator Op(const CastableTypedEnumResult<E>& aR1, \
79 const CastableTypedEnumResult<E>& aR2) \
80 { \
81 return ReturnType(OtherType(aR1) Op OtherType(aR2)); \
84 MOZ_CASTABLETYPEDENUMRESULT_BINOP(|, E, CastableTypedEnumResult<E>)
85 MOZ_CASTABLETYPEDENUMRESULT_BINOP(&, E, CastableTypedEnumResult<E>)
86 MOZ_CASTABLETYPEDENUMRESULT_BINOP(^, E, CastableTypedEnumResult<E>)
87 MOZ_CASTABLETYPEDENUMRESULT_BINOP(==, E, bool)
88 MOZ_CASTABLETYPEDENUMRESULT_BINOP(!=, E, bool)
89 MOZ_CASTABLETYPEDENUMRESULT_BINOP(||, bool, bool)
90 MOZ_CASTABLETYPEDENUMRESULT_BINOP(&&, bool, bool)
92 template <typename E>
93 MOZ_CONSTEXPR CastableTypedEnumResult<E>
94 operator ~(const CastableTypedEnumResult<E>& aR)
96 return CastableTypedEnumResult<E>(~(E(aR)));
99 #define MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(Op) \
100 template<typename E> \
101 E& \
102 operator Op(E& aR1, \
103 const CastableTypedEnumResult<E>& aR2) \
105 return aR1 Op E(aR2); \
108 MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(&=)
109 MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(|=)
110 MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP(^=)
112 #undef MOZ_CASTABLETYPEDENUMRESULT_COMPOUND_ASSIGN_OP
114 #undef MOZ_CASTABLETYPEDENUMRESULT_BINOP
116 namespace detail {
117 template<typename E>
118 struct UnsignedIntegerTypeForEnum
119 : UnsignedStdintTypeForSize<sizeof(E)>
123 } // namespace mozilla
125 #define MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, Op) \
126 inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
127 operator Op(Name a, Name b) \
129 typedef mozilla::CastableTypedEnumResult<Name> Result; \
130 typedef mozilla::detail::UnsignedIntegerTypeForEnum<Name>::Type U; \
131 return Result(Name(U(a) Op U(b))); \
134 inline Name& \
135 operator Op##=(Name& a, Name b) \
137 return a = a Op b; \
141 * MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS generates standard bitwise operators
142 * for the given enum type. Use this to enable using an enum type as bit-field.
144 #define MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(Name) \
145 MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, |) \
146 MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, &) \
147 MOZ_MAKE_ENUM_CLASS_BINOP_IMPL(Name, ^) \
148 inline MOZ_CONSTEXPR mozilla::CastableTypedEnumResult<Name> \
149 operator~(Name a) \
151 typedef mozilla::CastableTypedEnumResult<Name> Result; \
152 typedef mozilla::detail::UnsignedIntegerTypeForEnum<Name>::Type U; \
153 return Result(Name(~(U(a)))); \
156 #endif // mozilla_TypedEnumBits_h