![]() |
XII Release 0.1.0
|
The xiiBitflags class allows you to work with type-safe bitflags. More...
#include <Bitflags.h>
Public Types | |
using | ConstIterator = xiiBitIterator<Enum, false> |
Public Member Functions | |
XII_ALWAYS_INLINE | xiiBitflags () |
Constructor. Initializes the flags to the default value. | |
XII_ALWAYS_INLINE | xiiBitflags (Enum flag1) |
Converts the incoming type to xiiBitflags<T> | |
XII_ALWAYS_INLINE void | operator= (Enum flag1) |
XII_ALWAYS_INLINE constexpr bool | operator== (const StorageType rhs) const |
Comparison operator. | |
XII_ALWAYS_INLINE constexpr bool | operator== (const xiiBitflags< T > &rhs) const |
Comparison operator. | |
XII_ALWAYS_INLINE void | Clear () |
Clears all flags. | |
XII_ALWAYS_INLINE bool | IsSet (Enum flag) const |
Checks if certain flags are set within the bitfield. | |
XII_ALWAYS_INLINE bool | AreAllSet (const xiiBitflags< T > &rhs) const |
Returns whether all the given flags are set. | |
XII_ALWAYS_INLINE bool | AreNoneSet (const xiiBitflags< T > &rhs) const |
Returns whether none of the given flags is set. | |
XII_ALWAYS_INLINE bool | IsAnySet (const xiiBitflags< T > &rhs) const |
Returns whether any of the given flags is set. | |
XII_ALWAYS_INLINE bool | IsStrictlyAnySet (const xiiBitflags< T > &rhs) const |
Returns whether there are strictly any of the given flags set. | |
XII_ALWAYS_INLINE void | Add (const xiiBitflags< T > &rhs) |
Sets the given flag. | |
XII_ALWAYS_INLINE void | Remove (const xiiBitflags< T > &rhs) |
Removes the given flag. | |
XII_ALWAYS_INLINE void | Toggle (const xiiBitflags< T > &rhs) |
Toggles the state of the given flag. | |
XII_ALWAYS_INLINE void | AddOrRemove (const xiiBitflags< T > &rhs, bool bState) |
Sets or clears the given flag. | |
XII_ALWAYS_INLINE xiiBitflags< T > | operator| (const xiiBitflags< T > &rhs) const |
Returns an object that has the flags of this and rhs combined. | |
XII_ALWAYS_INLINE xiiBitflags< T > | operator& (const xiiBitflags< T > &rhs) const |
Returns an object that has the flags that were set both in this and rhs. | |
XII_ALWAYS_INLINE void | operator|= (const xiiBitflags< T > &rhs) |
Modifies this to also contain the bits from rhs. | |
XII_ALWAYS_INLINE void | operator&= (const xiiBitflags< T > &rhs) |
Modifies this to only contain the bits that were set in this and rhs. | |
XII_ALWAYS_INLINE StorageType | GetValue () const |
Returns the stored value as the underlying integer type. | |
XII_ALWAYS_INLINE void | SetValue (StorageType value) |
Overwrites the flags with a new value. | |
XII_ALWAYS_INLINE bool | IsNoFlagSet () const |
Returns true if not a single bit is set. | |
XII_ALWAYS_INLINE bool | IsAnyFlagSet () const |
Returns true if any bitflag is set. | |
XII_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. | |
XII_ALWAYS_INLINE ConstIterator | GetEndIterator () const |
Returns an invalid iterator. Needed to support range based for loops. | |
The xiiBitflags class allows you to work with type-safe bitflags.
xiiBitflags takes a struct as its template parameter, which contains an enum for the available flag values. xiiBitflags 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. xiiBitflags solves this problem. However the flag type used to instantiate xiiBitflags must fulfill some requirements.
There are two ways to define your bitflags type, that can be used with xiiBitflags.
The easier, less powerful way: Use the XII_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 a xiiBitflags 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 alias 'StorageType' is also mandatory, such that xiiBitflags can access it.
Finally the macro XII_DECLARE_FLAGS_OPERATORS will define the required operator to be able to combine bitflags of your type. I.e. it enables to write xiiBitflags<SimpleRenderFlags> f = EnableEffects | EnableLighting;
For a real world usage example, see xiiCVarFlags.