enum_flags.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /************************************************************************************
  2. * *
  3. * Copyright (c) 2014 - 2018 Axel Menzel <info@rttr.org> *
  4. * *
  5. * This file is part of RTTR (Run Time Type Reflection) *
  6. * License: MIT License *
  7. * *
  8. * Permission is hereby granted, free of charge, to any person obtaining *
  9. * a copy of this software and associated documentation files (the "Software"), *
  10. * to deal in the Software without restriction, including without limitation *
  11. * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  12. * and/or sell copies of the Software, and to permit persons to whom the *
  13. * Software is furnished to do so, subject to the following conditions: *
  14. * *
  15. * The above copyright notice and this permission notice shall be included in *
  16. * all copies or substantial portions of the Software. *
  17. * *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
  24. * SOFTWARE. *
  25. * *
  26. *************************************************************************************/
  27. #ifndef RTTR_ENUM_FLAGS_H_
  28. #define RTTR_ENUM_FLAGS_H_
  29. #include "rttr/detail/base/core_prerequisites.h"
  30. #include "rttr/detail/misc/std_type_traits.h"
  31. #include <type_traits>
  32. #include <cstdint>
  33. namespace rttr
  34. {
  35. namespace detail
  36. {
  37. class enum_flag;
  38. }
  39. /*!
  40. * The \ref enum_flags class template is used to store OR-combinations of enum values in a type-safe way.
  41. *
  42. * The values are stored internally inside an integer (unsigned or signed, depending on the underlying type of the enum).
  43. * Using values from other enums or raw integer (except 0) with this class will result in a compile time error.
  44. *
  45. * In order to use this class with your own enum, use RTTR_DECLARE_FLAGS() and RTTR_DECLARE_ENUM_FLAGS_OPERATORS().
  46. *
  47. * Typical Usage
  48. * -------------
  49. *
  50. * \code{.cpp}
  51. *
  52. * enum class my_option
  53. * {
  54. * ALL_DISABLED = 0,
  55. * OPTION_1 = 1,
  56. * OPTION_2 = 2,
  57. * OPTION_3 = 4,
  58. * OPTION_4 = 8
  59. * };
  60. *
  61. * RTTR_DECLARE_FLAGS(my_options, my_option)
  62. * RTTR_DECLARE_ENUM_FLAGS_OPERATORS(my_options)
  63. *
  64. * void my_func(my_options flags)
  65. * {
  66. * if (flags.test_flag(my_option::OPTION_1)
  67. * {
  68. * // ...
  69. * }
  70. *
  71. * if (flags.test_flag(my_option::OPTION_2)
  72. * {
  73. * // ...
  74. * }
  75. * }
  76. *
  77. * \endcode
  78. */
  79. template<typename Enum>
  80. class enum_flags
  81. {
  82. static_assert(sizeof(Enum) <= sizeof(int32_t), "Cannot store enums value with the given type."
  83. "Please use an enum which fits into an 'int32_t'." );
  84. public:
  85. using type = Enum;
  86. using enum_type = detail::conditional_t<std::is_signed<typename std::underlying_type<Enum>::type>::value,
  87. int32_t,
  88. uint32_t>;
  89. using zero = enum_type*;
  90. /*!
  91. * Creates an enum_flags object with no flags set.
  92. */
  93. RTTR_CONSTEXPR RTTR_INLINE enum_flags(zero = nullptr) RTTR_NOEXCEPT;
  94. /*!
  95. * Creates a enum_flags object with the given flag \p flag.
  96. */
  97. RTTR_CONSTEXPR RTTR_INLINE enum_flags(Enum flag) RTTR_NOEXCEPT;
  98. /*!
  99. * Creates an enum_flags object initialized with the given integer value \p value.
  100. *
  101. * \remark enum_flag is a wrapper class around an integer to avoid creation
  102. * of enum_flags object from enum values.
  103. */
  104. RTTR_CONSTEXPR RTTR_INLINE enum_flags(detail::enum_flag v) RTTR_NOEXCEPT;
  105. /////////////////////////////////////////////////////////////////////////////////
  106. /*!
  107. * \brief Performs a bitwise `AND` operation with \p mask
  108. * and store the result in this object.
  109. *
  110. * \return A reference to this object.
  111. */
  112. RTTR_CXX14_CONSTEXPR RTTR_INLINE enum_flags& operator&=(int mask) RTTR_NOEXCEPT;
  113. /*!
  114. * \brief Performs a bitwise `AND` operation with \p mask
  115. * and store the result in this object.
  116. *
  117. * \return A reference to this object.
  118. */
  119. RTTR_CXX14_CONSTEXPR RTTR_INLINE enum_flags& operator&=(uint32_t mask) RTTR_NOEXCEPT;
  120. /*!
  121. * \brief Performs a bitwise `AND` operation with \p mask
  122. * and store the result in this object.
  123. *
  124. * \return A reference to this object.
  125. */
  126. RTTR_CXX14_CONSTEXPR RTTR_INLINE enum_flags& operator&=(Enum mask) RTTR_NOEXCEPT;
  127. /*!
  128. * \brief Performs a bitwise `OR` operation with \p f
  129. * and store the result in this object.
  130. *
  131. * \return A reference to this object.
  132. */
  133. RTTR_CXX14_CONSTEXPR RTTR_INLINE enum_flags& operator|=(enum_flags f) RTTR_NOEXCEPT;
  134. /*!
  135. * \brief Performs a bitwise `OR` operation with \p f
  136. * and store the result in this object.
  137. *
  138. * \return A reference to this object.
  139. */
  140. RTTR_CXX14_CONSTEXPR RTTR_INLINE enum_flags& operator|=(Enum f) RTTR_NOEXCEPT;
  141. /*!
  142. * \brief Performs a bitwise `XOR` operation with \p f
  143. * and store the result in this object.
  144. *
  145. * \return A reference to this object.
  146. */
  147. RTTR_CXX14_CONSTEXPR RTTR_INLINE enum_flags& operator^=(enum_flags f) RTTR_NOEXCEPT;
  148. /*!
  149. * \brief Performs a bitwise `XOR` operation with \p f
  150. * and store the result in this object.
  151. *
  152. * \return A reference to this object.
  153. */
  154. RTTR_CXX14_CONSTEXPR RTTR_INLINE enum_flags& operator^=(Enum f) RTTR_NOEXCEPT;
  155. /*!
  156. * \brief Performs a bitwise `XOR` operation with \p f
  157. * and store the result in this object.
  158. *
  159. * \return A reference to this object.
  160. */
  161. RTTR_CONSTEXPR RTTR_INLINE operator enum_type() const RTTR_NOEXCEPT;
  162. /////////////////////////////////////////////////////////////////////////////////
  163. /*!
  164. * \brief Performs a bitwise `OR` operation on this object and \p f
  165. * and return the result as new enum_flags object.
  166. *
  167. * \return A enum_flags object containing the result of the bitwise `OR` operation on this object and \p f.
  168. */
  169. RTTR_CONSTEXPR RTTR_INLINE enum_flags operator|(Enum f) const RTTR_NOEXCEPT;
  170. /*!
  171. * \brief Performs a bitwise `OR` operation on this object and \p f
  172. * and return the result as new enum_flags object.
  173. *
  174. * \return A enum_flags object containing the result of the bitwise `OR` operation on this object and \p f.
  175. */
  176. RTTR_CONSTEXPR RTTR_INLINE enum_flags operator|(enum_flags f) const RTTR_NOEXCEPT;
  177. /*!
  178. * \brief Performs a bitwise `XOR` operation on this object and \p f
  179. * and return the result as new enum_flags object.
  180. *
  181. * \return A enum_flags object containing the result of the bitwise `XOR` operation on this object and \p f.
  182. */
  183. RTTR_CONSTEXPR RTTR_INLINE enum_flags operator^(Enum f) const RTTR_NOEXCEPT;
  184. /*!
  185. * \brief Performs a bitwise `XOR` operation on this object and \p f
  186. * and return the result as new enum_flags object.
  187. *
  188. * \return A enum_flags object containing the result of the bitwise `XOR` operation on this object and \p f.
  189. */
  190. RTTR_CONSTEXPR RTTR_INLINE enum_flags operator^(enum_flags f) const RTTR_NOEXCEPT;
  191. /*!
  192. * \brief Performs a bitwise `AND` operation on this object and \p f
  193. * and return the result as new enum_flags object.
  194. *
  195. * \return A enum_flags object containing the result of the bitwise `AND` operation on this object and \p f.
  196. */
  197. RTTR_CONSTEXPR RTTR_INLINE enum_flags operator&(Enum f) const RTTR_NOEXCEPT;
  198. /*!
  199. * \brief Performs a bitwise `AND` operation on this object and \p mask
  200. * and return the result as new enum_flags object.
  201. *
  202. * \return A enum_flags object containing the result of the bitwise `AND` operation on this object and \p mask.
  203. */
  204. RTTR_CONSTEXPR RTTR_INLINE enum_flags operator&(int mask) const RTTR_NOEXCEPT;
  205. /*!
  206. * \brief Performs a bitwise `AND` operation on this object and \p mask
  207. * and return the result as new enum_flags object.
  208. *
  209. * \return A enum_flags object containing the result of the bitwise `AND` operation on this object and \p mask.
  210. */
  211. RTTR_CONSTEXPR RTTR_INLINE enum_flags operator&(uint32_t mask) const RTTR_NOEXCEPT;
  212. /*!
  213. * \brief Performs a bitwise negation of the current object
  214. * and return the result as new enum_flags object.
  215. *
  216. * \return A enum_flags object that contains the bitwise negation of this object.
  217. */
  218. RTTR_CONSTEXPR RTTR_INLINE enum_flags operator~() const RTTR_NOEXCEPT;
  219. /*!
  220. * \brief This will test whether a flag was set or not.
  221. *
  222. * \return `true`, when no flag is set, otherwise `false`.
  223. */
  224. RTTR_CONSTEXPR RTTR_INLINE bool operator!() const RTTR_NOEXCEPT;
  225. /*!
  226. * \brief This will test whether the given flag \p flag was set.
  227. *
  228. * \return `true`, when the flag is set, otherwise `false`.
  229. */
  230. RTTR_CONSTEXPR RTTR_INLINE bool test_flag(Enum flag) const RTTR_NOEXCEPT;
  231. private:
  232. enum_type m_value;
  233. };
  234. namespace detail
  235. {
  236. /*!
  237. * Simple helper class to avoid the creation of `OR` combination with enum values and raw integers.
  238. *
  239. */
  240. class invalid_enum_flag
  241. {
  242. public:
  243. RTTR_CONSTEXPR RTTR_INLINE explicit invalid_enum_flag(int v){}
  244. };
  245. } // end namespace detail
  246. #ifdef DOXYGEN
  247. /*!
  248. * This macro expands to:
  249. * \code{.cpp}
  250. * using Flags = rttr::enum_flags<Enum>;
  251. * \endcode
  252. *
  253. * \p Flags is the name of the alias for `rttr::enum_flags<Enum>`.
  254. *
  255. * \p Enum is the name of the existing enum.
  256. */
  257. #define RTTR_DECLARE_FLAGS(Flags, Enum)
  258. /*!
  259. * This macro declares the a global operator `|` for enums of type \ref enum_flags<T>
  260. *
  261. * \see RTTR_DECLARE_FLAGS()
  262. */
  263. #define RTTR_DECLARE_ENUM_FLAGS_OPERATORS(Flags)
  264. #else
  265. #define RTTR_DECLARE_FLAGS(Flags, Enum) \
  266. using Flags = rttr::enum_flags<Enum>;
  267. #define RTTR_DECLARE_ENUM_FLAGS_OPERATORS(Flags) \
  268. RTTR_CONSTEXPR RTTR_INLINE rttr::enum_flags<Flags::type> operator|(Flags::type lhs, Flags::type rhs) RTTR_NOEXCEPT \
  269. { \
  270. return (rttr::enum_flags<Flags::type>(lhs) | rhs); \
  271. } \
  272. RTTR_CONSTEXPR RTTR_INLINE rttr::enum_flags<Flags::type> operator|(Flags::type lhs, rttr::enum_flags<Flags::type> rhs) RTTR_NOEXCEPT \
  273. { \
  274. return (rhs | lhs); \
  275. } \
  276. RTTR_CONSTEXPR RTTR_INLINE rttr::detail::invalid_enum_flag operator|(Flags::type lhs, int rhs) \
  277. { \
  278. return rttr::detail::invalid_enum_flag(int(lhs) | rhs); \
  279. }
  280. #endif
  281. } // end namespace rttr
  282. #include "rttr/detail/impl/enum_flags_impl.h"
  283. #endif // RTTR_ENUM_FLAGS_H_