Mistake on this page?
Report an issue in GitHub or email us
mbed_enum_flags.h
1 /*
2  * Copyright (c) 2020 ARM Limited. All rights reserved.
3  * SPDX-License-Identifier: Apache-2.0
4  * Licensed under the Apache License, Version 2.0 (the License); you may
5  * not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef MBED_SCOPED_ENUM_FLAGS_H
18 #define MBED_SCOPED_ENUM_FLAGS_H
19 
20 #include <type_traits>
21 
22 #define ENUM_FLAG_BITWISE_OPERATOR(T, OP) \
23 inline constexpr T operator OP(T lhs, T rhs) \
24 { \
25  return T (static_cast<std::underlying_type_t<T>>(lhs) OP \
26  static_cast<std::underlying_type_t<T>>(rhs)); \
27 }
28 
29 
30 #define ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, OP) \
31 inline constexpr T &operator OP(T &lhs, T rhs) \
32 { \
33  return lhs = lhs OP rhs; \
34 }
35 
36 
37 /**
38  * @brief Applies bitwise operators to a enum class defined elsewhere.
39  *
40  * @param T The enum class typename
41  *
42  * This macro applies the bitwise negate, AND, OR, XOR operators and the
43  * corresponding assignment operators to an existing enum class. The macro
44  * uses underlying type traits to convert back and forth.
45  *
46  * Usage:
47  * @code
48  * external_enum.h:
49  *
50  * enum class SpokenLanguages : uint8_t {
51  * Sindarin = (1 << 0),
52  * Westron = (1 << 1),
53  * Rohirric = (1 << 2),
54  * BlackSpeech = (1 << 3)
55  * };
56  *
57  * my_code.cpp:
58  *
59  * #include "mbed_enum_flags.h"
60  * #include "external_enum.h"
61  *
62  * MBED_ENUM_FLAG_APPLY_OPERATORS(SpokenLanguages);
63  *
64  * SpokenLanguages gandalf = SpokenLanguages::Sindarin | SpokenLanguages::Westron |
65  * SpokenLanguages::Rohirric | SpokenLanguages::BlackSpeech;
66  * @endcode
67  *
68  */
69 #define MBED_ENUM_FLAG_APPLY_OPERATORS(T) \
70  inline constexpr T operator ~(T lhs) \
71  { \
72  return T(~static_cast<std::underlying_type_t<T>>(lhs)); \
73  } \
74  ENUM_FLAG_BITWISE_OPERATOR(T, |) \
75  ENUM_FLAG_BITWISE_OPERATOR(T, ^) \
76  ENUM_FLAG_BITWISE_OPERATOR(T, &) \
77  ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, |=) \
78  ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, ^=) \
79  ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, &=) \
80  static_assert(true, "This assert true is to require a semicolon to terminate the macro.") \
81 
82 
83 /** @private
84  *
85  * @brief Bitwise definition macro with underlying type.
86  *
87  * Not part of public API. Do not use directly. Use MBED_SCOPED_ENUM_FLAGS instead.
88  */
89 #define SCOPED_ENUM_FLAGS_TYPED(T, UNDERLYING_T) \
90  enum class T : UNDERLYING_T; \
91  MBED_ENUM_FLAG_APPLY_OPERATORS(T); \
92  enum class T : UNDERLYING_T
93 
94 /** @private
95  *
96  * @brief Bitwise definition macro with default underlying type.
97  *
98  * Not part of public API. Do not use directly. Use MBED_SCOPED_ENUM_FLAGS instead.
99  */
100 #define SCOPED_ENUM_FLAGS_UNTYPED(T) \
101  enum class T; \
102  MBED_ENUM_FLAG_APPLY_OPERATORS(T); \
103  enum class T
104 
105 #define MBED_SCOPED_ENUM_FLAGS_CHOOSER(_1, _2, NAME, ...) NAME
106 
107 /**
108  * @brief Creates an enum class with bitwise operator overloads.
109  *
110  * @param T The enum class typename
111  * @param UNDERLYING_T Optional: specify the underlying integral type. If
112  * omitted, the enum class underlying type will be the
113  * compiler default.
114  *
115  * This macro creates both the enum class type and defines NOT, AND, OR, and
116  * XOR operators. It also defines as three bitwise assignment operators, AND,
117  * OR, and XOR. It allows for the scoped nature of the enum class, but adds back
118  * the bitwise operators that were missing.
119  *
120  * This macro uses type traits to convert between the underlying type and back
121  * again for the bitwise operations.
122  *
123  * Usage:
124  * @code
125  * my_nice_enum_class_with_flags.h:
126  *
127  * MBED_SCOPED_ENUM_FLAGS(MyFlagName) {
128  * HasEars = (1 << 0),
129  * HasFur = (1 << 1),
130  * LaysEggs = (1 << 2),
131  * Meows = (1 << 3),
132  * Polydactyl = (1 << 30)
133  * };
134  *
135  * MBED_SCOPED_ENUM_FLAGS(SpokenLanguages, uint8_t) {
136  * Sindarin = (1 << 0),
137  * Westron = (1 << 1),
138  * Rohirric = (1 << 2),
139  * BlackSpeech = (1 << 3)
140  * };
141  *
142  * my_enum_class_flag_consumer.h:
143  *
144  * class EnumEater {
145  * public:
146  * EnumEater(MyFlagName flags) : _flags(flags) {}
147  *
148  * static MyFlagName DefaultFlags = MyFlagName::HasEars | MyFlagName::Meows;
149  *
150  * bool is_cat() const {
151  * return ((_flags & DefaultFlags) == DefaultFlags) &&
152  * ((_flags & MyFlagName::LaysEggs) == MyFlagName());
153  * }
154  * private:
155  * MyFlagName _flags;
156  * };
157  *
158  * bool is_Gandalf(SpokenLanguages flags) {
159  * return flags == (SpokenLanguages::Sindarin | SpokenLanguages::Westron |
160  * SpokenLanguages::SpeaksRohirric | SpokenLanguages::BlackSpeech);
161  * }
162  * @endcode
163  *
164  */
165 #define MBED_SCOPED_ENUM_FLAGS(...) MBED_SCOPED_ENUM_FLAGS_CHOOSER(__VA_ARGS__, SCOPED_ENUM_FLAGS_TYPED, SCOPED_ENUM_FLAGS_UNTYPED)(__VA_ARGS__)
166 
167 #endif //MBED_SCOPED_ENUM_FLAGS_H
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.