![]() |
ezEngine
Release 25.03
|
The ezBitflags class allows you to work with type-safe bitflags. More...
#include <Bitflags.h>
Public Types | |
using | ConstIterator = ezBitIterator< Enum, false > |
Public Member Functions | |
EZ_ALWAYS_INLINE | ezBitflags () |
Constructor. Initializes the flags to the default value. | |
EZ_ALWAYS_INLINE | ezBitflags (Enum flag1) |
Converts the incoming type to ezBitflags<T> | |
EZ_ALWAYS_INLINE void | operator= (Enum flag1) |
EZ_ALWAYS_INLINE bool | operator== (const StorageType rhs) const |
Comparison operator. | |
EZ_ALWAYS_INLINE bool | operator!= (const StorageType rhs) const |
Comparison operator. | |
EZ_ALWAYS_INLINE bool | operator== (const ezBitflags< T > &rhs) const |
Comparison operator. | |
EZ_ALWAYS_INLINE bool | operator!= (const ezBitflags< T > &rhs) const |
Comparison operator. | |
EZ_ALWAYS_INLINE void | Clear () |
Clears all flags. | |
EZ_ALWAYS_INLINE bool | IsSet (Enum flag) const |
Checks if certain flags are set within the bitfield. | |
EZ_ALWAYS_INLINE bool | AreAllSet (const ezBitflags< T > &rhs) const |
Returns whether all the given flags are set. | |
EZ_ALWAYS_INLINE bool | AreNoneSet (const ezBitflags< T > &rhs) const |
Returns whether none of the given flags is set. | |
EZ_ALWAYS_INLINE bool | IsAnySet (const ezBitflags< T > &rhs) const |
Returns whether any of the given flags is set. | |
EZ_ALWAYS_INLINE void | Add (const ezBitflags< T > &rhs) |
Sets the given flag. | |
EZ_ALWAYS_INLINE void | Remove (const ezBitflags< T > &rhs) |
Removes the given flag. | |
EZ_ALWAYS_INLINE void | Toggle (const ezBitflags< T > &rhs) |
Toggles the state of the given flag. | |
EZ_ALWAYS_INLINE void | AddOrRemove (const ezBitflags< T > &rhs, bool bState) |
Sets or clears the given flag. | |
EZ_ALWAYS_INLINE ezBitflags< T > | operator| (const ezBitflags< T > &rhs) const |
Returns an object that has the flags of this and rhs combined. | |
EZ_ALWAYS_INLINE ezBitflags< T > | operator& (const ezBitflags< T > &rhs) const |
Returns an object that has the flags that were set both in this and rhs. | |
EZ_ALWAYS_INLINE void | operator|= (const ezBitflags< T > &rhs) |
Modifies this to also contain the bits from rhs. | |
EZ_ALWAYS_INLINE void | operator&= (const ezBitflags< T > &rhs) |
Modifies this to only contain the bits that were set in this and rhs. | |
EZ_ALWAYS_INLINE StorageType | GetValue () const |
Returns the stored value as the underlying integer type. | |
EZ_ALWAYS_INLINE void | SetValue (StorageType value) |
Overwrites the flags with a new value. | |
EZ_ALWAYS_INLINE bool | IsNoFlagSet () const |
Returns true if not a single bit is set. | |
EZ_ALWAYS_INLINE bool | IsAnyFlagSet () const |
Returns true if any bitflag is set. | |
EZ_ALWAYS_INLINE ConstIterator | GetIterator () const |
Returns a constant iterator to the very first set bit. Note that due to the way iterating through bits is accelerated, changes to the bitflags will not affect the iterator after creation. | |
EZ_ALWAYS_INLINE ConstIterator | GetEndIterator () const |
Returns an invalid iterator. Needed to support range based for loops. | |
The ezBitflags class allows you to work with type-safe bitflags.
ezBitflags takes a struct as its template parameter, which contains an enum for the available flag values. ezBitflags wraps this type in a way which enables the compiler to do type-checks. This makes it very easy to document and enforce what flags are to be used in an interface. For example, in traditional C++ code, you usually need to have an integer as a function parameter type, when that parameter is supposed to take flags. However, WHICH flags (e.g. from which enum) cannot be enforced through compile time checks. Thus it is difficult for the user to see whether he used the correct type, and it is impossible for the compiler to help find such bugs. ezBitflags solves this problem. However the flag type used to instantiate ezBitflags must fulfill some requirements.
There are two ways to define your bitflags type, that can be used with ezBitflags.
The easier, less powerful way: Use the EZ_DECLARE_FLAGS() macro.
Example:
This will declare a type 'SimpleRenderFlags' which contains three different flags. You can then create a function which takes flags like this:
And this function can be called like this:
However it will refuse to compile with anything else, for example this will not work:
The second way to declare your bitflags type allows even more flexibility. Here you need to declare your bitflag type manually:
Here we declare a struct which contains our enum that contains all the flags that we want to have. This enum can contain flags that are combinations of other flags. Note also the 'Default' flag, which is mandatory.
The 'Bits' struct enables debuggers to show exactly which flags are enabled (with nice names) when you inspect an ezBitflags instance. You could leave this struct empty, but then your debugger can not show helpful information about the flags anymore. The Bits struct should contain one named entry for each individual bit. E.g. here only the flags 'EnableEffects', 'EnableLighting' and 'EnableShadows' actually map to single bits, the other flags are combinations of those. Therefore the Bits struct only specifies names for those first three Bits.
The typedef 'StorageType' is also mandatory, such that ezBitflags can access it.
Finally the macro EZ_DECLARE_FLAGS_OPERATORS will define the required operator to be able to combine bitflags of your type. I.e. it enables to write ezBitflags<SimpleRenderFlags> f = EnableEffects | EnableLighting;
For a real world usage example, see ezCVarFlags.