| // Copyright 2015 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #pragma once |
| |
| #include <type_traits> |
| |
| // This header defines some utitily methods to manipulate scoped enums as flags |
| // C++11 scoped enums by default don't support flag operations (e.g. if (a & b)) |
| // We need to define bitwise operations for them to be able to have strongly |
| // typed flags in our code. |
| // |
| // To enable the flag operators for your enum, most probably you just need to |
| // include this file. The only exception is if your enum is located in some |
| // namespace other than android, android::base or global. In that case you also |
| // need to add the following using to bring in the operators: |
| // |
| // using namespace ::android::base::EnumFlags; |
| |
| namespace android { |
| namespace base { |
| namespace EnumFlags { |
| |
| // A predicate which checks if template agument is a scoped enum |
| template<class E> |
| using is_scoped_enum = std::integral_constant< |
| bool, |
| std::is_enum<E>::value && !std::is_convertible<E, int>::value>; |
| |
| template <class E> |
| using underlying_enum_type = typename std::underlying_type<E>::type; |
| |
| template <class E, class Res = E> |
| using enable_if_scoped_enum = |
| typename std::enable_if<is_scoped_enum<E>::value, Res>::type; |
| |
| template <class E> |
| enable_if_scoped_enum<E> operator|(E l, E r) { |
| return static_cast<E>(static_cast<underlying_enum_type<E>>(l) |
| | static_cast<underlying_enum_type<E>>(r)); |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E> operator&(E l, E r) { |
| return static_cast<E>(static_cast<underlying_enum_type<E>>(l) |
| & static_cast<underlying_enum_type<E>>(r)); |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E> operator~(E e) { |
| return static_cast<E>(~static_cast<underlying_enum_type<E>>(e)); |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E> operator|=(E& l, E r) { |
| return l = (l | r); |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E> operator&=(E& l, E r) { |
| return l = (l & r); |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E, bool> operator!(E e) { |
| return !static_cast<underlying_enum_type<E>>(e); |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E, bool> operator!=(E e, int val) { |
| return static_cast<underlying_enum_type<E>>(e) != |
| static_cast<underlying_enum_type<E>>(val); |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E, bool> operator!=(int val, E e) { |
| return e != val; |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E, bool> operator==(E e, int val) { |
| return static_cast<underlying_enum_type<E>>(e) == |
| static_cast<underlying_enum_type<E>>(val); |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E, bool> operator==(int val, E e) { |
| return e == val; |
| } |
| |
| template <class E> |
| enable_if_scoped_enum<E, bool> nonzero(E e) { |
| return static_cast<underlying_enum_type<E>>(e) != 0; |
| } |
| |
| } // namespace EnumFlags |
| |
| // For the ADL to kick in let's make sure we bring all the operators into our |
| // main AndroidEmu namespaces... |
| using namespace ::android::base::EnumFlags; |
| |
| } // namespace base |
| |
| using namespace ::android::base::EnumFlags; |
| |
| } // namespace android |
| |
| // ... and into the global one, where most of the client functions are |
| using namespace ::android::base::EnumFlags; |