From 77a1a72c460d2beb83ca9c1252e9ac637ef12881 Mon Sep 17 00:00:00 2001 From: pea-pod Date: Tue, 7 Apr 2020 22:15:07 -0500 Subject: [PATCH] Add enum class flag definition to platform --- platform/mbed_enum_flags.h | 167 +++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 platform/mbed_enum_flags.h diff --git a/platform/mbed_enum_flags.h b/platform/mbed_enum_flags.h new file mode 100644 index 0000000000..edeee31dec --- /dev/null +++ b/platform/mbed_enum_flags.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2020 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBED_SCOPED_ENUM_FLAGS_H +#define MBED_SCOPED_ENUM_FLAGS_H + +#include + +#define ENUM_FLAG_BITWISE_OPERATOR(T, OP) \ +inline constexpr T operator OP(T lhs, T rhs) \ +{ \ + return T (static_cast>(lhs) OP \ + static_cast>(rhs)); \ +} + + +#define ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, OP) \ +inline constexpr T &operator OP(T &lhs, T rhs) \ +{ \ + return lhs = lhs OP rhs; \ +} + + +/** + * @brief Applies bitwise operators to a enum class defined elsewhere. + * + * @param T The enum class typename + * + * This macro applies the bitwise negate, AND, OR, XOR operators and the + * corresponding assignment operators to an existing enum class. The macro + * uses underlying type traits to convert back and forth. + * + * Usage: + * @code + * external_enum.h: + * + * enum class SpokenLanguages : uint8_t { + * Sindarin = (1 << 0), + * Westron = (1 << 1), + * Rohirric = (1 << 2), + * BlackSpeech = (1 << 3) + * }; + * + * my_code.cpp: + * + * #include "mbed_enum_flags.h" + * #include "external_enum.h" + * + * MBED_ENUM_FLAG_APPLY_OPERATORS(SpokenLanguages); + * + * SpokenLanguages gandalf = SpokenLanguages::Sindarin | SpokenLanguages::Westron | + * SpokenLanguages::Rohirric | SpokenLanguages::BlackSpeech; + * @endcode + * + */ +#define MBED_ENUM_FLAG_APPLY_OPERATORS(T) \ + inline constexpr T operator ~(T lhs) \ + { \ + return T(~static_cast>(lhs)); \ + } \ + ENUM_FLAG_BITWISE_OPERATOR(T, |) \ + ENUM_FLAG_BITWISE_OPERATOR(T, ^) \ + ENUM_FLAG_BITWISE_OPERATOR(T, &) \ + ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, |=) \ + ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, ^=) \ + ENUM_FLAG_COMPOUND_ASSIGNMENT_OPERATOR(T, &=) \ + static_assert(true, "This assert true is to require a semicolon to terminate the macro.") \ + + +/** @private + * + * @brief Bitwise definition macro with underlying type. + * + * Not part of public API. Do not use directly. Use MBED_SCOPED_ENUM_FLAGS instead. + */ +#define SCOPED_ENUM_FLAGS_TYPED(T, UNDERLYING_T) \ + enum class T : UNDERLYING_T; \ + MBED_ENUM_FLAG_APPLY_OPERATORS(T); \ + enum class T : UNDERLYING_T + +/** @private + * + * @brief Bitwise definition macro with default underlying type. + * + * Not part of public API. Do not use directly. Use MBED_SCOPED_ENUM_FLAGS instead. + */ +#define SCOPED_ENUM_FLAGS_UNTYPED(T) \ + enum class T; \ + MBED_ENUM_FLAG_APPLY_OPERATORS(T); \ + enum class T + +#define MBED_SCOPED_ENUM_FLAGS_CHOOSER(_1, _2, NAME, ...) NAME + +/** + * @brief Creates an enum class with bitwise operator overloads. + * + * @param T The enum class typename + * @param UNDERLYING_T Optional: specify the underlying integral type. If + * omitted, the enum class underlying type will be the + * compiler default. + * + * This macro creates both the enum class type and defines NOT, AND, OR, and + * XOR operators. It also defines as three bitwise assignment operators, AND, + * OR, and XOR. It allows for the scoped nature of the enum class, but adds back + * the bitwise operators that were missing. + * + * This macro uses type traits to convert between the underlying type and back + * again for the bitwise operations. + * + * Usage: + * @code + * my_nice_enum_class_with_flags.h: + * + * MBED_SCOPED_ENUM_FLAGS(MyFlagName) { + * HasEars = (1 << 0), + * HasFur = (1 << 1), + * LaysEggs = (1 << 2), + * Meows = (1 << 3), + * Polydactyl = (1 << 30) + * }; + * + * MBED_SCOPED_ENUM_FLAGS(SpokenLanguages, uint8_t) { + * Sindarin = (1 << 0), + * Westron = (1 << 1), + * Rohirric = (1 << 2), + * BlackSpeech = (1 << 3) + * }; + * + * my_enum_class_flag_consumer.h: + * + * class EnumEater { + * public: + * EnumEater(MyFlagName flags) : _flags(flags) {} + * + * static MyFlagName DefaultFlags = MyFlagName::HasEars | MyFlagName::Meows; + * + * bool is_cat() const { + * return ((_flags & DefaultFlags) == DefaultFlags) && + * ((_flags & MyFlagName::LaysEggs) == MyFlagName()); + * } + * private: + * MyFlagName _flags; + * }; + * + * bool is_Gandalf(SpokenLanguages flags) { + * return flags == (SpokenLanguages::Sindarin | SpokenLanguages::Westron | + * SpokenLanguages::SpeaksRohirric | SpokenLanguages::BlackSpeech); + * } + * @endcode + * + */ +#define MBED_SCOPED_ENUM_FLAGS(...) MBED_SCOPED_ENUM_FLAGS_CHOOSER(__VA_ARGS__, SCOPED_ENUM_FLAGS_TYPED, SCOPED_ENUM_FLAGS_UNTYPED)(__VA_ARGS__) + +#endif //MBED_SCOPED_ENUM_FLAGS_H