mirror of https://github.com/ARMmbed/mbed-os.git
168 lines
5.0 KiB
C++
168 lines
5.0 KiB
C++
/*
|
|
* 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 <type_traits>
|
|
|
|
#define ENUM_FLAG_BITWISE_OPERATOR(T, OP) \
|
|
inline constexpr T operator OP(T lhs, T rhs) \
|
|
{ \
|
|
return T (static_cast<std::underlying_type_t<T>>(lhs) OP \
|
|
static_cast<std::underlying_type_t<T>>(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<std::underlying_type_t<T>>(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
|