Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenlib/BLI_utildefines.h
| Show First 20 Lines • Show All 774 Lines • ▼ Show 20 Lines | |||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name C++ Macros | /** \name C++ Macros | ||||
| * \{ */ | * \{ */ | ||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||
| /* Useful to port C code using enums to C++ where enums are strongly typed. | /* Useful to port C code using enums to C++ where enums are strongly typed. | ||||
| * To use after the enum declaration. */ | * To use after the enum declaration. | ||||
| /* If any enumerator `C` is set to say `A|B`, then `C` would be the max enum value. */ | * #_max_enum_value is used to create a bitmask for the ~ operator. | ||||
| * #_max_enum_value should be the largest power of two that is a valid enum value */ | |||||
| # define ENUM_OPERATORS(_enum_type, _max_enum_value) \ | # define ENUM_OPERATORS(_enum_type, _max_enum_value) \ | ||||
| extern "C++" { \ | extern "C++" { \ | ||||
| inline constexpr _enum_type operator|(_enum_type a, _enum_type b) \ | inline constexpr _enum_type operator|(_enum_type a, _enum_type b) \ | ||||
| { \ | { \ | ||||
| return static_cast<_enum_type>(static_cast<uint64_t>(a) | static_cast<uint64_t>(b)); \ | return static_cast<_enum_type>(static_cast<uint64_t>(a) | static_cast<uint64_t>(b)); \ | ||||
| } \ | } \ | ||||
| inline constexpr _enum_type operator&(_enum_type a, _enum_type b) \ | inline constexpr _enum_type operator&(_enum_type a, _enum_type b) \ | ||||
| { \ | { \ | ||||
| return static_cast<_enum_type>(static_cast<uint64_t>(a) & static_cast<uint64_t>(b)); \ | return static_cast<_enum_type>(static_cast<uint64_t>(a) & static_cast<uint64_t>(b)); \ | ||||
| } \ | } \ | ||||
| BLI_STATIC_ASSERT((static_cast<uint64_t>(_max_enum_value) & \ | |||||
deadpin: I'd add this assert block either at the very top or very bottom of the macro instead of in the… | |||||
| (static_cast<uint64_t>(_max_enum_value) - 1)) == 0, \ | |||||
| "Invalid value: _max_enum_value must be zero or a power of two \n"); \ | |||||
deadpinUnsubmitted Done Inline ActionsThere's no need to have a trailing \n character in your message. Clang literally writes out \n in the output and MSVC quotes the string, so you get a line with just an ending quote for it. deadpin: There's no need to have a trailing \n character in your message. Clang literally writes out \n… | |||||
deadpinUnsubmitted Not Done Inline ActionsI think we'd actually want to disallow 0 right? Would a 0 ever be useable? deadpin: I think we'd actually want to disallow 0 right? Would a 0 ever be useable? | |||||
Ethan1080AuthorUnsubmitted Done Inline Actions0 results in a bitmask that is 1 for all bits. It might not be useful, but at least it does not leave holes in the bitmask, so it is not as bad as other non-power-of-twos. The assert cannot prevent the programmer from putting the wrong power of two. It only prevents values that result in bitmasks holes or more than one switch over point from zeros to ones. That said, an explicit check for _max_enum_value not equals 0 could be added. Ethan1080: 0 results in a bitmask that is 1 for all bits. It might not be useful, but at least it does not… | |||||
| inline constexpr _enum_type operator~(_enum_type a) \ | inline constexpr _enum_type operator~(_enum_type a) \ | ||||
| { \ | { \ | ||||
| return static_cast<_enum_type>(~static_cast<uint64_t>(a) & \ | return static_cast<_enum_type>(~static_cast<uint64_t>(a) & \ | ||||
| (2 * static_cast<uint64_t>(_max_enum_value) - 1)); \ | ((static_cast<uint64_t>(_max_enum_value) << 1) - 1)); \ | ||||
| } \ | } \ | ||||
| inline _enum_type &operator|=(_enum_type &a, _enum_type b) \ | inline _enum_type &operator|=(_enum_type &a, _enum_type b) \ | ||||
| { \ | { \ | ||||
| return a = static_cast<_enum_type>(static_cast<uint64_t>(a) | static_cast<uint64_t>(b)); \ | return a = static_cast<_enum_type>(static_cast<uint64_t>(a) | static_cast<uint64_t>(b)); \ | ||||
| } \ | } \ | ||||
| inline _enum_type &operator&=(_enum_type &a, _enum_type b) \ | inline _enum_type &operator&=(_enum_type &a, _enum_type b) \ | ||||
| { \ | { \ | ||||
| return a = static_cast<_enum_type>(static_cast<uint64_t>(a) & static_cast<uint64_t>(b)); \ | return a = static_cast<_enum_type>(static_cast<uint64_t>(a) & static_cast<uint64_t>(b)); \ | ||||
| Show All 36 Lines | |||||
I'd add this assert block either at the very top or very bottom of the macro instead of in the middle of the operators.