// -*- C++ -*- (c) 2013 Vladimír Štill #if __cplusplus < 201103L #error "strongenumflag is only supported with c++11 or newer" #endif #include #ifndef WIBBLE_STRONGENUMFLAG_H #define WIBBLE_STRONGENUMFLAG_H namespace wibble { template< typename E > using is_enum_class = std::integral_constant< bool, std::is_enum< E >::value && !std::is_convertible< E, int >::value >; template< typename Self > struct StrongEnumFlags { static_assert( is_enum_class< Self >::value, "Not an enum class." ); using This = StrongEnumFlags< Self >; using UnderlyingType = typename std::underlying_type< Self >::type; constexpr StrongEnumFlags() noexcept : store( 0 ) { } constexpr StrongEnumFlags( Self flag ) noexcept : store( static_cast< UnderlyingType >( flag ) ) { } explicit constexpr StrongEnumFlags( UnderlyingType st ) noexcept : store( st ) { } constexpr explicit operator UnderlyingType() const noexcept { return store; } This &operator|=( This o ) noexcept { store |= o.store; return *this; } This &operator&=( This o ) noexcept { store &= o.store; return *this; } This &operator^=( This o ) noexcept { store ^= o.store; return *this; } friend constexpr This operator|( This a, This b ) noexcept { return This( a.store | b.store ); } friend constexpr This operator&( This a, This b ) noexcept { return This( a.store & b.store ); } friend constexpr This operator^( This a, This b ) noexcept { return This( a.store ^ b.store ); } friend constexpr bool operator==( This a, This b ) noexcept { return a.store == b.store; } friend constexpr bool operator!=( This a, This b ) noexcept { return a.store != b.store; } constexpr bool has( Self x ) const noexcept { return (*this) & x; } constexpr operator bool() const noexcept { return store; } private: UnderlyingType store; }; // don't catch integral types and classical enum! template< typename Self, typename = typename std::enable_if< is_enum_class< Self >::value >::type > constexpr StrongEnumFlags< Self > operator|( Self a, Self b ) noexcept { using Ret = StrongEnumFlags< Self >; return Ret( a ) | Ret( b ); } template< typename Self, typename = typename std::enable_if< is_enum_class< Self >::value >::type > constexpr StrongEnumFlags< Self > operator&( Self a, Self b ) noexcept { using Ret = StrongEnumFlags< Self >; return Ret( a ) & Ret( b ); } } #endif // WIBBLE_STRONGENUMFLAG_H