// Copyright 2017 The Chromium OS Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef LIBBRILLO_BRILLO_ENUM_FLAGS_H_ #define LIBBRILLO_BRILLO_ENUM_FLAGS_H_ #include // This is a helper for generating type-safe bitwise operators for flags that // are defined by an enumeration. By default, when a bitwise operation is // performed on two enumerators of an enumeration, the result is the base type // (int), not a value of the enumeration: // // enum SomeEnumOfFlags { // ONE = 1, // TWO = 2, // THREE = 4, // // etc. // }; // // SomeEnumOfFlags flags = static_cast(ONE | TWO); // // By enabling these operators for an enum type: // // DECLARE_FLAGS_ENUM(SomeEnumOfFlags); // // The syntax is simplified to: // // SomeEnumOfFlags flags = ONE | TWO; // // But the following still does not compile without using a cast (as is // expected): // // SomeEnumOfFlags flags = ONE | 2; // This is the macro used to declare that an enum type |ENUM| should have bit- // wise operators defined for it. #define DECLARE_FLAGS_ENUM(ENUM) \ template struct EnumFlagTraitType; \ template <> struct EnumFlagTraitType { using EnumFlagType = ENUM; }; \ EnumFlagTraitType GetEnumFlagTraitType(ENUM) __attribute__((used)); // Setup the templates used to declare that the operators should exist for a // given type T. namespace enum_details { template using FlagEnumTraits = decltype(GetEnumFlagTraitType(std::declval())); template using Void = void; template struct IsFlagEnum : std::false_type {}; template struct IsFlagEnum::EnumFlagType>> : std::true_type {}; } // namespace enum_details // The operators themselves, conditional on having been declared that they are // flag-style enums. // T operator~(T&) template constexpr typename std::enable_if::value, T>::type operator~(const T& l) { return static_cast( ~static_cast::type>(l)); } // T operator|(T&, T&) template constexpr typename std::enable_if::value, T>::type operator|(const T& l, const T& r) { return static_cast( static_cast::type>(l) | static_cast::type>(r)); } // T operator&(T&, T&) template constexpr typename std::enable_if::value, T>::type operator&(const T& l, const T& r) { return static_cast( static_cast::type>(l) & static_cast::type>(r)); } // T operator^(T&, T&) template constexpr typename std::enable_if::value, T>::type operator^( const T& l, const T& r) { return static_cast(static_cast::type>(l) ^ static_cast::type>(r)); }; // T operator|=(T&, T&) template constexpr typename std::enable_if::value, T>::type operator|=( T& l, const T& r) { return l = static_cast( static_cast::type>(l) | static_cast::type>(r)); }; // T operator&=(T&, T&) template constexpr typename std::enable_if::value, T>::type operator&=( T& l, const T& r) { return l = static_cast( static_cast::type>(l) & static_cast::type>(r)); }; // T operator^=(T&, T&) template constexpr typename std::enable_if::value, T>::type operator^=( T& l, const T& r) { return l = static_cast( static_cast::type>(l) ^ static_cast::type>(r)); }; #endif // LIBBRILLO_BRILLO_ENUM_FLAGS_H_