Mbed OS Reference
Loading...
Searching...
No Matches
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) \
23inline 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) \
31inline 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