FlagSet.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Base/PrimitiveTypes.h"
  5. #include <type_traits>
  6. namespace Urho3D
  7. {
  8. /// Define bitwise operators for scoped enum.
  9. /// Use !! to convert scoped enum to bool
  10. #define URHO3D_FLAGS(EnumClass) \
  11. inline constexpr EnumClass operator |(const EnumClass lhs, const EnumClass rhs) \
  12. { \
  13. using UT = std::underlying_type_t<EnumClass>; \
  14. return static_cast<EnumClass>(static_cast<UT>(lhs) | static_cast<UT>(rhs)); \
  15. } \
  16. inline constexpr EnumClass& operator |=(EnumClass& lhs, const EnumClass rhs) \
  17. { \
  18. using UT = std::underlying_type_t<EnumClass>; \
  19. lhs = static_cast<EnumClass>(static_cast<UT>(lhs) | static_cast<UT>(rhs)); \
  20. return lhs; \
  21. } \
  22. inline constexpr EnumClass operator &(const EnumClass lhs, const EnumClass rhs) \
  23. { \
  24. using UT = std::underlying_type_t<EnumClass>; \
  25. return static_cast<EnumClass>(static_cast<UT>(lhs) & static_cast<UT>(rhs)); \
  26. } \
  27. inline constexpr EnumClass& operator &=(EnumClass& lhs, const EnumClass rhs) \
  28. { \
  29. using UT = std::underlying_type_t<EnumClass>; \
  30. lhs = static_cast<EnumClass>(static_cast<UT>(lhs) & static_cast<UT>(rhs)); \
  31. return lhs; \
  32. } \
  33. inline constexpr EnumClass operator ^(const EnumClass lhs, const EnumClass rhs) \
  34. { \
  35. using UT = std::underlying_type_t<EnumClass>; \
  36. return static_cast<EnumClass>(static_cast<UT>(lhs) ^ static_cast<UT>(rhs)); \
  37. } \
  38. inline constexpr EnumClass& operator ^=(EnumClass& lhs, const EnumClass rhs) \
  39. { \
  40. using UT = std::underlying_type_t<EnumClass>; \
  41. lhs = static_cast<EnumClass>(static_cast<UT>(lhs) ^ static_cast<UT>(rhs)); \
  42. return lhs; \
  43. } \
  44. inline constexpr EnumClass operator ~(const EnumClass rhs) \
  45. { \
  46. using UT = std::underlying_type_t<EnumClass>; \
  47. return static_cast<EnumClass>(~static_cast<UT>(rhs)); \
  48. } \
  49. inline constexpr bool operator ==(const EnumClass lhs, const std::underlying_type_t<EnumClass> rhs) \
  50. { \
  51. using UT = std::underlying_type_t<EnumClass>; \
  52. return static_cast<UT>(lhs) == rhs; \
  53. } \
  54. inline constexpr bool operator ==(const std::underlying_type_t<EnumClass> lhs, const EnumClass rhs) \
  55. { \
  56. using UT = std::underlying_type_t<EnumClass>; \
  57. return lhs == static_cast<UT>(rhs); \
  58. } \
  59. inline constexpr bool operator !=(const EnumClass lhs, const std::underlying_type_t<EnumClass> rhs) \
  60. { \
  61. using UT = std::underlying_type_t<EnumClass>; \
  62. return static_cast<UT>(lhs) != rhs; \
  63. } \
  64. inline constexpr bool operator !=(const std::underlying_type_t<EnumClass> lhs, const EnumClass rhs) \
  65. { \
  66. using UT = std::underlying_type_t<EnumClass>; \
  67. return lhs != static_cast<UT>(rhs); \
  68. } \
  69. inline constexpr bool operator !(const EnumClass rhs) \
  70. { \
  71. using UT = std::underlying_type_t<EnumClass>; \
  72. return static_cast<UT>(rhs) == 0; \
  73. }
  74. /// Make bitwise operators (| & ^ ~) automatically construct FlagSet from Enum.
  75. #define URHO3D_AUTOMATIC_FLAGSET(Enum) \
  76. inline Urho3D::FlagSet<Enum> operator | (const Enum lhs, const Enum rhs) { return Urho3D::FlagSet<Enum>(lhs) | rhs; } \
  77. inline Urho3D::FlagSet<Enum> operator & (const Enum lhs, const Enum rhs) { return Urho3D::FlagSet<Enum>(lhs) & rhs; } \
  78. inline Urho3D::FlagSet<Enum> operator ^ (const Enum lhs, const Enum rhs) { return Urho3D::FlagSet<Enum>(lhs) ^ rhs; } \
  79. inline Urho3D::FlagSet<Enum> operator ~ (const Enum rhs) { return ~Urho3D::FlagSet<Enum>(rhs); }
  80. /// Declare FlagSet for specific enum and create operators for automatic FlagSet construction.
  81. #define URHO3D_FLAGSET(enumName, flagsetName) \
  82. URHO3D_AUTOMATIC_FLAGSET(enumName) \
  83. using flagsetName = Urho3D::FlagSet<enumName>
  84. /// A set of flags defined by an Enum.
  85. template <class E>
  86. class FlagSet
  87. {
  88. public:
  89. /// Enum type.
  90. using Enum = E;
  91. /// Integer type.
  92. using Integer = typename std::underlying_type<Enum>::type;
  93. public:
  94. /// Ctor by integer.
  95. explicit FlagSet(Integer value)
  96. : value_(value)
  97. {
  98. }
  99. /// Empty constructor.
  100. FlagSet() = default;
  101. /// Copy constructor.
  102. FlagSet(const FlagSet& another) = default;
  103. /// Construct from Enum value.
  104. FlagSet(const Enum value)
  105. : value_(static_cast<Integer>(value))
  106. {
  107. }
  108. /// Assignment operator from flagset.
  109. FlagSet& operator = (const FlagSet& rhs) = default;
  110. /// Bitwise AND against Enum value.
  111. FlagSet& operator &= (const Enum value)
  112. {
  113. value_ &= static_cast<Integer>(value);
  114. return *this;
  115. }
  116. /// Bitwise AND against flagset value.
  117. FlagSet& operator &= (const FlagSet value)
  118. {
  119. value_ &= value.value_;
  120. return *this;
  121. }
  122. /// Bitwise OR against Enum value.
  123. FlagSet& operator |= (const Enum value)
  124. {
  125. value_ |= static_cast<Integer>(value);
  126. return *this;
  127. }
  128. /// Bitwise OR against flagset value.
  129. FlagSet& operator |= (const FlagSet value)
  130. {
  131. value_ |= value.value_;
  132. return *this;
  133. }
  134. /// Bitwise XOR against Enum value.
  135. FlagSet& operator ^= (const Enum value)
  136. {
  137. value_ ^= static_cast<Integer>(value);
  138. return *this;
  139. }
  140. /// Bitwise XOR against flagset value.
  141. FlagSet& operator ^= (const FlagSet value)
  142. {
  143. value_ ^= value.value_;
  144. return *this;
  145. }
  146. /// Bitwise AND against Enum value.
  147. FlagSet operator & (const Enum value) const
  148. {
  149. return FlagSet(value_ & static_cast<Integer>(value));
  150. }
  151. /// Bitwise AND against flagset value.
  152. FlagSet operator & (const FlagSet value) const
  153. {
  154. return FlagSet(value_ & value.value_);
  155. }
  156. /// Bitwise OR against Enum value.
  157. FlagSet operator | (const Enum value) const
  158. {
  159. return FlagSet(value_ | static_cast<Integer>(value));
  160. }
  161. /// Bitwise OR against flagset value.
  162. FlagSet operator | (const FlagSet value) const
  163. {
  164. return FlagSet(value_ | value.value_);
  165. }
  166. /// Bitwise XOR against Enum value.
  167. FlagSet operator ^ (const Enum value) const
  168. {
  169. return FlagSet(value_ ^ static_cast<Integer>(value));
  170. }
  171. /// Bitwise XOR against flagset value.
  172. FlagSet operator ^ (const FlagSet value) const
  173. {
  174. return FlagSet(value_ ^ value.value_);
  175. }
  176. /// Bitwise negation.
  177. FlagSet operator ~ () const
  178. {
  179. return FlagSet(~value_);
  180. }
  181. /// Boolean negation.
  182. bool operator ! () const
  183. {
  184. return !value_;
  185. }
  186. /// Returns true if any flag is set.
  187. explicit operator bool () const
  188. {
  189. return value_ != 0;
  190. }
  191. /// Cast to underlying type of enum.
  192. operator Integer() const
  193. {
  194. return value_;
  195. }
  196. /// Cast to enum value.
  197. explicit operator Enum() const
  198. {
  199. return static_cast<Enum>(value_);
  200. }
  201. /// Cast to double. Used by Lua bindings.
  202. explicit operator double() const
  203. {
  204. return static_cast<double>(value_);
  205. }
  206. /// Equality check against enum value.
  207. bool operator ==(Enum rhs) const
  208. {
  209. return value_ == static_cast<Integer>(rhs);
  210. }
  211. /// Equality check against another flagset.
  212. bool operator ==(FlagSet rhs) const
  213. {
  214. return value_ == rhs.value_;
  215. }
  216. /// Non-equality check against enum value.
  217. bool operator !=(Enum rhs) const
  218. {
  219. return !(*this == rhs);
  220. }
  221. /// Non-equality check against another flagset value.
  222. bool operator !=(FlagSet rhs) const
  223. {
  224. return !(*this == rhs);
  225. }
  226. /// Return true if specified enum value is set.
  227. inline bool Test(const Enum value) const
  228. {
  229. return Test(static_cast<Integer>(value));
  230. }
  231. /// Return true if specified bits are set.
  232. inline bool Test(const Integer flags) const
  233. {
  234. return (value_ & flags) == flags && (flags != 0 || value_ == flags);
  235. }
  236. /// Return underlying integer (constant).
  237. Integer AsInteger() const { return value_; }
  238. /// Return underlying integer (non-constant).
  239. Integer& AsInteger() { return value_; }
  240. /// Return hash value.
  241. hash32 ToHash() const { return static_cast<hash32>(value_); }
  242. protected:
  243. /// Value.
  244. Integer value_ = 0;
  245. };
  246. }