1 // Copyright 2015 The Android Open Source Project
2 //
3 // This software is licensed under the terms of the GNU General Public
4 // License version 2, as published by the Free Software Foundation, and
5 // may be copied, distributed, and modified under those terms.
6 //
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License for more details.
11 
12 #pragma once
13 
14 #include <type_traits>
15 
16 // This header defines some utitily methods to manipulate scoped enums as flags
17 // C++11 scoped enums by default don't support flag operations (e.g. if (a & b))
18 // We need to define bitwise operations for them to be able to have strongly
19 // typed flags in our code.
20 //
21 // To enable the flag operators for your enum, most probably you just need to
22 // include this file. The only exception is if your enum is located in some
23 // namespace other than android, android::base or global. In that case you also
24 // need to add the following using to bring in the operators:
25 //
26 // using namespace ::android::base::EnumFlags;
27 
28 namespace android {
29 namespace base {
30 namespace EnumFlags {
31 
32 // A predicate which checks if template agument is a scoped enum
33 template<class E>
34 using is_scoped_enum = std::integral_constant<
35         bool,
36         std::is_enum<E>::value && !std::is_convertible<E, int>::value>;
37 
38 template <class E>
39 using underlying_enum_type = typename std::underlying_type<E>::type;
40 
41 template <class E, class Res = E>
42 using enable_if_scoped_enum =
43     typename std::enable_if<is_scoped_enum<E>::value, Res>::type;
44 
45 template <class E>
46 enable_if_scoped_enum<E> operator|(E l, E r) {
47     return static_cast<E>(static_cast<underlying_enum_type<E>>(l)
48                           | static_cast<underlying_enum_type<E>>(r));
49 }
50 
51 template <class E>
52 enable_if_scoped_enum<E> operator&(E l, E r) {
53     return static_cast<E>(static_cast<underlying_enum_type<E>>(l)
54                           & static_cast<underlying_enum_type<E>>(r));
55 }
56 
57 template <class E>
58 enable_if_scoped_enum<E> operator~(E e) {
59     return static_cast<E>(~static_cast<underlying_enum_type<E>>(e));
60 }
61 
62 template <class E>
63 enable_if_scoped_enum<E> operator|=(E& l, E r) {
64     return l = (l | r);
65 }
66 
67 template <class E>
68 enable_if_scoped_enum<E> operator&=(E& l, E r) {
69     return l = (l & r);
70 }
71 
72 template <class E>
73 enable_if_scoped_enum<E, bool> operator!(E e) {
74     return !static_cast<underlying_enum_type<E>>(e);
75 }
76 
77 template <class E>
78 enable_if_scoped_enum<E, bool> operator!=(E e, int val) {
79     return static_cast<underlying_enum_type<E>>(e) !=
80             static_cast<underlying_enum_type<E>>(val);
81 }
82 
83 template <class E>
84 enable_if_scoped_enum<E, bool> operator!=(int val, E e) {
85     return e != val;
86 }
87 
88 template <class E>
89 enable_if_scoped_enum<E, bool> operator==(E e, int val) {
90     return static_cast<underlying_enum_type<E>>(e) ==
91             static_cast<underlying_enum_type<E>>(val);
92 }
93 
94 template <class E>
95 enable_if_scoped_enum<E, bool> operator==(int val, E e) {
96     return e == val;
97 }
98 
99 template <class E>
nonzero(E e)100 enable_if_scoped_enum<E, bool> nonzero(E e) {
101     return static_cast<underlying_enum_type<E>>(e) != 0;
102 }
103 
104 }  // namespace EnumFlags
105 
106 // For the ADL to kick in let's make sure we bring all the operators into our
107 // main AndroidEmu namespaces...
108 using namespace ::android::base::EnumFlags;
109 
110 }  // namespace base
111 
112 using namespace ::android::base::EnumFlags;
113 
114 }  // namespace android
115 
116 // ... and into the global one, where most of the client functions are
117 using namespace ::android::base::EnumFlags;
118