1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
21 #define INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
23 #include <sal/config.h>
26 #include <type_traits>
32 template<typename T
> inline
33 typename
std::enable_if
<std::is_signed
<T
>::value
, bool>::type
isNonNegative(
39 template<typename T
> inline
40 typename
std::enable_if
<std::is_unsigned
<T
>::value
, bool>::type
isNonNegative(T
)
47 template<typename T
> struct typed_flags
{};
49 #if defined __GNUC__ && __GNUC__ == 4 && __GNUC_MINOR__ <= 6 && \
51 // use largest sensible unsigned type as fallback
52 #define O3TL_STD_UNDERLYING_TYPE_E unsigned long long
54 #define O3TL_STD_UNDERLYING_TYPE_E typename std::underlying_type<E>::type
57 /// Mark a (scoped) enumeration as a set of bit flags, with accompanying
61 /// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {};
63 /// All relevant values must be non-negative. (Typically, the enumeration's
64 /// underlying type will either be fixed and unsigned, or it will be unfixed---
65 /// and can thus default to a signed type---and all enumerators will have non-
68 /// \param E the enumeration type.
69 /// \param M the all-bits-set value for the bit flags.
70 template<typename E
, O3TL_STD_UNDERLYING_TYPE_E M
>
71 struct is_typed_flags
{
73 M
>= 0, "is_typed_flags expects only non-negative bit values");
79 explicit Wrap(O3TL_STD_UNDERLYING_TYPE_E value
):
81 { assert(detail::isNonNegative(value
)); }
83 operator E() { return static_cast<E
>(value_
); }
85 explicit operator O3TL_STD_UNDERLYING_TYPE_E() { return value_
; }
87 explicit operator bool() { return value_
!= 0; }
90 O3TL_STD_UNDERLYING_TYPE_E value_
;
93 static O3TL_STD_UNDERLYING_TYPE_E
const mask
= M
;
99 inline typename
o3tl::typed_flags
<E
>::Wrap
operator ~(E rhs
) {
101 o3tl::detail::isNonNegative(
102 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
103 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
104 o3tl::typed_flags
<E
>::mask
105 & ~static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
109 inline typename
o3tl::typed_flags
<E
>::Wrap
operator ~(
110 typename
o3tl::typed_flags
<E
>::Wrap rhs
)
112 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
113 o3tl::typed_flags
<E
>::mask
114 & ~static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
118 inline typename
o3tl::typed_flags
<E
>::Wrap
operator ^(E lhs
, E rhs
) {
120 o3tl::detail::isNonNegative(
121 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
123 o3tl::detail::isNonNegative(
124 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
125 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
126 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
127 ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
131 inline typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
132 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
135 o3tl::detail::isNonNegative(
136 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
137 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
138 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
139 ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
143 inline typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
144 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
147 o3tl::detail::isNonNegative(
148 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
149 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
150 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
151 ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
155 inline typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
156 typename
o3tl::typed_flags
<E
>::Wrap lhs
,
157 typename
o3tl::typed_flags
<E
>::Wrap rhs
)
159 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
160 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
161 ^ static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
165 inline typename
o3tl::typed_flags
<E
>::Wrap
operator &(E lhs
, E rhs
) {
167 o3tl::detail::isNonNegative(
168 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
170 o3tl::detail::isNonNegative(
171 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
172 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
173 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
174 & static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
178 inline typename
o3tl::typed_flags
<E
>::Wrap
operator &(
179 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
182 o3tl::detail::isNonNegative(
183 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
184 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
185 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
186 & static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
190 inline typename
o3tl::typed_flags
<E
>::Wrap
operator &(
191 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
194 o3tl::detail::isNonNegative(
195 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
196 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
197 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
198 & static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
202 inline typename
o3tl::typed_flags
<E
>::Wrap
operator &(
203 typename
o3tl::typed_flags
<E
>::Wrap lhs
,
204 typename
o3tl::typed_flags
<E
>::Wrap rhs
)
206 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
207 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
208 & static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
212 inline typename
o3tl::typed_flags
<E
>::Wrap
operator |(E lhs
, E rhs
) {
214 o3tl::detail::isNonNegative(
215 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
217 o3tl::detail::isNonNegative(
218 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
219 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
220 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
221 | static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
225 inline typename
o3tl::typed_flags
<E
>::Wrap
operator |(
226 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
229 o3tl::detail::isNonNegative(
230 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
231 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
232 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
233 | static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
237 inline typename
o3tl::typed_flags
<E
>::Wrap
operator |(
238 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
241 o3tl::detail::isNonNegative(
242 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
243 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
244 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
245 | static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
249 inline typename
o3tl::typed_flags
<E
>::Wrap
operator |(
250 typename
o3tl::typed_flags
<E
>::Wrap lhs
,
251 typename
o3tl::typed_flags
<E
>::Wrap rhs
)
253 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
254 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)
255 | static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
));
259 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(E
& lhs
, E rhs
) {
261 o3tl::detail::isNonNegative(
262 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
264 o3tl::detail::isNonNegative(
265 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
271 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(
272 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
275 o3tl::detail::isNonNegative(
276 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
282 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(E
& lhs
, E rhs
) {
284 o3tl::detail::isNonNegative(
285 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
287 o3tl::detail::isNonNegative(
288 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
294 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(
295 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
298 o3tl::detail::isNonNegative(
299 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
305 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(E
& lhs
, E rhs
) {
307 o3tl::detail::isNonNegative(
308 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
310 o3tl::detail::isNonNegative(
311 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(rhs
)));
317 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(
318 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
321 o3tl::detail::isNonNegative(
322 static_cast<O3TL_STD_UNDERLYING_TYPE_E
>(lhs
)));
327 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
329 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */