From 56bfb9804c75ce1625517373148e9af11b6b7442 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 8 Jan 2022 15:48:40 +0100 Subject: [PATCH] Base: [skip ci] support bitmask operations for enums --- src/Base/Bitmask.h | 97 +++++++++++++++++++++++++++++++++++++++++ src/Base/CMakeLists.txt | 1 + 2 files changed, 98 insertions(+) create mode 100644 src/Base/Bitmask.h diff --git a/src/Base/Bitmask.h b/src/Base/Bitmask.h new file mode 100644 index 0000000000..d4732ca418 --- /dev/null +++ b/src/Base/Bitmask.h @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (c) 2022 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 51 Franklin Street, * + * Fifth Floor, Boston, MA 02110-1301, USA * + * * + ***************************************************************************/ + +#include + +/*! + Using enum classes as type-safe bitmasks. + @code + enum class Color { + Red = 1 << 0, + Green = 1 << 1, + Blue = 1 << 2 + }; + ENABLE_BITMASK_OPERATORS(Color) + + Color yellow = Color::Red | Color::Green; + @endcode +*/ + +// Based on https://stackoverflow.com/questions/1448396/how-to-use-enums-as-flags-in-c +template struct enum_traits {}; + +template<> struct enum_traits { + struct _allow_bitops { + static constexpr bool allow_bitops = true; + }; + using allow_bitops = _allow_bitops; + + template + using t = typename std::enable_if::value && + enum_traits::allow_bitops, R>::type; + + template + using u = typename std::underlying_type::type; +}; + +template +constexpr enum_traits<>::t operator~(T a) { + return static_cast(~static_cast::u>(a)); +} +template +constexpr enum_traits<>::t operator|(T a, T b) { + return static_cast( + static_cast::u>(a) | + static_cast::u>(b)); +} +template +constexpr enum_traits<>::t operator&(T a, T b) { + return static_cast( + static_cast::u>(a) & + static_cast::u>(b)); +} +template +constexpr enum_traits<>::t operator^(T a, T b) { + return static_cast( + static_cast::u>(a) ^ + static_cast::u>(b)); +} +template +constexpr enum_traits<>::t operator|=(T& a, T b) { + a = a | b; + return a; +} +template +constexpr enum_traits<>::t operator&=(T& a, T b) { + a = a & b; + return a; +} +template +constexpr enum_traits<>::t operator^=(T& a, T b) { + a = a ^ b; + return a; +} + +#define ENABLE_BITMASK_OPERATORS(x) \ +template<> \ +struct enum_traits : \ + enum_traits<>::allow_bitops {}; diff --git a/src/Base/CMakeLists.txt b/src/Base/CMakeLists.txt index e3933d0541..c954558fcd 100644 --- a/src/Base/CMakeLists.txt +++ b/src/Base/CMakeLists.txt @@ -280,6 +280,7 @@ SET(FreeCADBase_HPP_SRCS Base64.h BaseClass.h BindingManager.h + Bitmask.h BoundBox.h Builder3D.h Console.h