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