1 // Copyright 2015 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include <type_traits>
18 
19 // This header defines some utitily methods to manipulate scoped enums as flags
20 // C++11 scoped enums by default don't support flag operations (e.g. if (a & b))
21 // We need to define bitwise operations for them to be able to have strongly
22 // typed flags in our code.
23 //
24 // To enable the flag operators for your enum, most probably you just need to
25 // include this file. The only exception is if your enum is located in some
26 // namespace other than android, android::base or global. In that case you also
27 // need to add the following using to bring in the operators:
28 //
29 // using namespace ::android::base::EnumFlags;
30 
31 namespace android {
32 namespace base {
33 namespace EnumFlags {
34 
35 // A predicate which checks if template agument is a scoped enum
36 template<class E>
37 using is_scoped_enum = std::integral_constant<
38         bool,
39         std::is_enum<E>::value && !std::is_convertible<E, int>::value>;
40 
41 template <class E>
42 using underlying_enum_type = typename std::underlying_type<E>::type;
43 
44 template <class E, class Res = E>
45 using enable_if_scoped_enum =
46     typename std::enable_if<is_scoped_enum<E>::value, Res>::type;
47 
48 template <class E>
49 enable_if_scoped_enum<E> operator|(E l, E r) {
50     return static_cast<E>(static_cast<underlying_enum_type<E>>(l)
51                           | static_cast<underlying_enum_type<E>>(r));
52 }
53 
54 template <class E>
55 enable_if_scoped_enum<E> operator&(E l, E r) {
56     return static_cast<E>(static_cast<underlying_enum_type<E>>(l)
57                           & static_cast<underlying_enum_type<E>>(r));
58 }
59 
60 template <class E>
61 enable_if_scoped_enum<E> operator~(E e) {
62     return static_cast<E>(~static_cast<underlying_enum_type<E>>(e));
63 }
64 
65 template <class E>
66 enable_if_scoped_enum<E> operator|=(E& l, E r) {
67     return l = (l | r);
68 }
69 
70 template <class E>
71 enable_if_scoped_enum<E> operator&=(E& l, E r) {
72     return l = (l & r);
73 }
74 
75 template <class E>
76 enable_if_scoped_enum<E, bool> operator!(E e) {
77     return !static_cast<underlying_enum_type<E>>(e);
78 }
79 
80 template <class E>
81 enable_if_scoped_enum<E, bool> operator!=(E e, int val) {
82     return static_cast<underlying_enum_type<E>>(e) !=
83             static_cast<underlying_enum_type<E>>(val);
84 }
85 
86 template <class E>
87 enable_if_scoped_enum<E, bool> operator!=(int val, E e) {
88     return e != val;
89 }
90 
91 template <class E>
92 enable_if_scoped_enum<E, bool> operator==(E e, int val) {
93     return static_cast<underlying_enum_type<E>>(e) ==
94             static_cast<underlying_enum_type<E>>(val);
95 }
96 
97 template <class E>
98 enable_if_scoped_enum<E, bool> operator==(int val, E e) {
99     return e == val;
100 }
101 
102 template <class E>
nonzero(E e)103 enable_if_scoped_enum<E, bool> nonzero(E e) {
104     return static_cast<underlying_enum_type<E>>(e) != 0;
105 }
106 
107 }  // namespace EnumFlags
108 
109 // For the ADL to kick in let's make sure we bring all the operators into our
110 // main AndroidEmu namespaces...
111 using namespace ::android::base::EnumFlags;
112 
113 }  // namespace base
114 
115 using namespace ::android::base::EnumFlags;
116 
117 }  // namespace android
118 
119 // ... and into the global one, where most of the client functions are
120 using namespace ::android::base::EnumFlags;
121