#ifndef flags_hh_INCLUDED #define flags_hh_INCLUDED #include #include "meta.hh" namespace Kakoune { template constexpr bool with_bit_ops(Meta::Type) { return false; } template using UnderlyingType = std::underlying_type_t; template using EnableIfWithBitOps = std::enable_if_t{}), T>; template using EnableIfWithoutBitOps = std::enable_if_t{}), T>; template> constexpr Flags operator|(Flags lhs, Flags rhs) { return (Flags)((UnderlyingType) lhs | (UnderlyingType) rhs); } template> Flags& operator|=(Flags& lhs, Flags rhs) { (UnderlyingType&) lhs |= (UnderlyingType) rhs; return lhs; } template struct TestableFlags { Flags value; constexpr operator bool() const { return (UnderlyingType)value; } constexpr operator Flags() const { return value; } constexpr operator UnderlyingType() const { return (UnderlyingType)value; } bool operator==(const TestableFlags& other) const { return value == other.value; } bool operator!=(const TestableFlags& other) const { return value != other.value; } }; template> constexpr TestableFlags operator&(Flags lhs, Flags rhs) { return { (Flags)((UnderlyingType) lhs & (UnderlyingType) rhs) }; } template> Flags& operator&=(Flags& lhs, Flags rhs) { (UnderlyingType&) lhs &= (UnderlyingType) rhs; return lhs; } template> constexpr Flags operator~(Flags lhs) { return (Flags)(~(UnderlyingType)lhs); } template> constexpr Flags operator^(Flags lhs, Flags rhs) { return (Flags)((UnderlyingType) lhs ^ (UnderlyingType) rhs); } template> Flags& operator^=(Flags& lhs, Flags rhs) { (UnderlyingType&) lhs ^= (UnderlyingType) rhs; return lhs; } } #endif // flags_hh_INCLUDED