diff --git a/include/ebcl/Types.hh b/include/ebcl/Types.hh index 870721c..5781117 100644 --- a/include/ebcl/Types.hh +++ b/include/ebcl/Types.hh @@ -9,6 +9,47 @@ namespace ebcl { +/*= FLAGS HELPER =============================================================*/ + +// This class is meant to be used along with an enum that represents flags. +// The values from the enum are considered to be bit numbers. +template< + typename Enum , + typename Storage = uint32_t +> class T_Flags +{ + private: + Storage flags_; + + public: + constexpr T_Flags( ) noexcept; + constexpr T_Flags( T_Flags const& other ) noexcept; + constexpr T_Flags( const Enum flag ) noexcept; + constexpr T_Flags( std::initializer_list< Enum > flags ) noexcept; + + explicit constexpr T_Flags( const Storage flags ) noexcept; + + constexpr T_Flags operator |=( T_Flags other ) noexcept; + constexpr T_Flags operator &=( T_Flags other ) noexcept; + constexpr T_Flags operator ^=( T_Flags other ) noexcept; + + constexpr T_Flags operator ~( ) const noexcept; + constexpr T_Flags operator &( T_Flags other ) const noexcept; + constexpr T_Flags operator |( T_Flags other ) const noexcept; + constexpr T_Flags operator ^( T_Flags other ) const noexcept; + + constexpr operator bool( ) const noexcept; + constexpr bool operator!( ) const noexcept; + explicit constexpr operator Storage( ) const noexcept; + + constexpr bool operator ==( const T_Flags other ) const noexcept; + constexpr bool operator !=( const T_Flags other ) const noexcept; + + constexpr bool isSet( const T_Flags value ) const noexcept; + constexpr bool isClear( const T_Flags value ) const noexcept; +}; + + /*= VARIANT TYPE =============================================================*/ // Forward declaration of the main variant type diff --git a/include/ebcl/inline/Types.hh b/include/ebcl/inline/Types.hh index 7d9e99f..d9375b7 100644 --- a/include/ebcl/inline/Types.hh +++ b/include/ebcl/inline/Types.hh @@ -8,6 +8,151 @@ namespace ebcl { +/*= FLAGS HELPER =============================================================*/ + +template< typename E , typename S > +inline constexpr T_Flags< E , S >::T_Flags( ) noexcept + : flags_( 0 ) +{ } + +template< typename E , typename S > +inline constexpr T_Flags< E , S >::T_Flags( + T_Flags< E , S > const& other ) noexcept + : flags_( other.flags_ ) +{ } + +template< typename E , typename S > +inline constexpr T_Flags< E , S >::T_Flags( + const E flag ) noexcept + : flags_( 1 << int( flag ) ) +{ } + +template< typename E , typename S > +inline constexpr T_Flags< E , S >::T_Flags( + std::initializer_list< E > flags ) noexcept + : flags_( 0 ) +{ + for ( auto f : flags ) { + flags_ |= ( 1 << int( f ) ); + } +} + +/*----------------------------------------------------------------------------*/ + +template< typename E , typename S > +inline constexpr T_Flags< E , S >::T_Flags( + const S flags ) noexcept + : flags_( flags ) +{ } + +/*----------------------------------------------------------------------------*/ + +template< typename E , typename S > +inline constexpr T_Flags< E , S > T_Flags< E , S >::operator |=( + const T_Flags< E , S > other ) noexcept +{ + flags_ |= other.flags_; + return *this; +} + +template< typename E , typename S > +inline constexpr T_Flags< E , S > T_Flags< E , S >::operator &=( + const T_Flags< E , S > other ) noexcept +{ + flags_ &= other.flags_; + return *this; +} + +template< typename E , typename S > +inline constexpr T_Flags< E , S > T_Flags< E , S >::operator ^=( + const T_Flags< E , S > other ) noexcept +{ + flags_ ^= other.flags_; + return *this; +} + +/*----------------------------------------------------------------------------*/ + +template< typename E , typename S > +inline constexpr T_Flags T_Flags< E , S >::operator ~( ) const noexcept +{ + return T_Flags( ~flags_ ); +} + +template< typename E , typename S > +inline constexpr T_Flags< E , S > T_Flags< E , S >::operator &( + const T_Flags< E , S > other ) const noexcept +{ + return T_Flags( flags_ & other.flags_ ); +} + +template< typename E , typename S > +inline constexpr T_Flags< E , S > T_Flags< E , S >::operator |( + const T_Flags< E , S > other ) const noexcept +{ + return T_Flags( flags_ | other.flags_ ); +} + +template< typename E , typename S > +inline constexpr T_Flags< E , S > T_Flags< E , S >::operator ^( + const T_Flags< E , S > other ) const noexcept +{ + return T_Flags( flags_ ^ other.flags_ ); +} + +/*----------------------------------------------------------------------------*/ + +template< typename E , typename S > +inline constexpr T_Flags< E , S >::operator bool( ) const noexcept +{ + return flags_ != 0; +} + +template< typename E , typename S > +inline constexpr bool T_Flags< E , S >::operator!( ) const noexcept +{ + return flags_ == 0; +} + +template< typename E , typename S > +inline constexpr T_Flags< E , S >::operator S( ) const noexcept +{ + return flags_; +} + +/*----------------------------------------------------------------------------*/ + +template< typename E , typename S > +inline constexpr bool T_Flags< E , S >::operator ==( + const T_Flags< E , S > other ) const noexcept +{ + return flags_ == other.flags_; +} + +template< typename E , typename S > +inline constexpr bool T_Flags< E , S >::operator !=( + const T_Flags< E , S > other ) const noexcept +{ + return flags_ != other.flags_; +} + +/*----------------------------------------------------------------------------*/ + +template< typename E , typename S > +inline constexpr bool T_Flags< E , S >::isSet( + const T_Flags< E , S > value ) const noexcept +{ + return ( *this & value ) == value; +} + +template< typename E , typename S > +inline constexpr bool T_Flags< E , S >::isClear( + const T_Flags< E , S > value ) const noexcept +{ + return !( *this & value ); +} + + /*= VARIANT TYPE =============================================================*/ template< typename T >