Skip to content

Commit d0d35c2

Browse files
authored
Merge pull request #12772 from pea-pod/scoped-enums
Add enum class flag definition to platform
2 parents 727cf54 + 77a1a72 commit d0d35c2

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

platform/mbed_enum_flags.h

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
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

0 commit comments

Comments
 (0)