From 718f1f67432b5c2e39c8c43c41a1bc0073ce040e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Sat, 23 Jun 2012 03:03:18 +0200 Subject: [PATCH] Set implementation for strongly-typed enums. --- src/Set.h | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/Set.h diff --git a/src/Set.h b/src/Set.h new file mode 100644 index 000000000..b3178bb14 --- /dev/null +++ b/src/Set.h @@ -0,0 +1,119 @@ +#ifndef Magnum_Set_h +#define Magnum_Set_h +/* + Copyright © 2010, 2011, 2012 Vladimír Vondruš + + This file is part of Magnum. + + Magnum is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License version 3 + only, as published by the Free Software Foundation. + + Magnum 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 Lesser General Public License version 3 for more details. +*/ + +/** @file + * @brief Class Magnum::Set + */ + +namespace Magnum { + +/** @ingroup utility +@brief %Set +@tparam T Enum type +@tparam U Underlying type of the enum + +Provides strongly-typed set-like functionality for strongly typed enums, such +as binary OR and AND operations. The only requirement for enum type is that +all the values must be binary exclusive. + +Desired usage is via typedef'ing and then calling SET_OPERATORS() macro with +the resulting type as parameter to have all the operators implemented. +@code +enum class State: unsigned char { + Ready = 0x01, + Waiting = 0x02, + Done = 0x04 +}; + +typedef Set States; +SET_OPERATORS(States) +@endcode +*/ +template class Set { + public: + typedef T Type; /**< @brief Enum type */ + typedef U UnderlyingType; /**< @brief Underlying type of the enum */ + + /** @brief Create empty set */ + constexpr inline Set(): value() {} + + /** @brief Create set from one value */ + constexpr inline Set(T value): value(static_cast(value)) {} + + /** @brief Add value to the set */ + constexpr inline Set operator|(T other) const { + return Set(value | static_cast(other)); + } + + /** @brief Union of two sets */ + constexpr inline Set operator|(Set other) const { + return Set(value | other.value); + } + + /** @brief Add value to the set and assign */ + inline Set& operator|=(T other) { + value |= static_cast(other); + return *this; + } + + /** @brief Union two sets and assign */ + inline Set& operator|=(Set other) { + value |= other.value; + return *this; + } + + /** @brief Check if given value is in the set */ + constexpr inline T operator&(T other) const { + return static_cast(value & static_cast(other)); + } + + /** @brief Intersection of two sets */ + constexpr inline Set operator&(Set other) const { + return Set(value & other.value); + } + + /** @brief Intersect two sets and assign */ + inline Set& operator&=(Set other) const { + value &= other.value; + return *this; + } + + /** @brief Value in underlying type */ + constexpr inline UnderlyingType toUnderlyingType() const { + return value; + } + + private: + constexpr inline explicit Set(UnderlyingType type): value(type) {} + + UnderlyingType value; +}; + +/** @hideinitializer +@brief Define out-of-class operators for given Set implementation +*/ +#define SET_OPERATORS(class) \ + inline constexpr class operator|(class::Type a, class b) { \ + return b | a; \ + } \ + inline constexpr class operator&(class::Type a, class b) { \ + return b & a; \ + } + +} + +#endif