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>
28 #include <config_global.h>
29 #include <sal/types.h>
35 template<typename T
> inline SAL_CONSTEXPR
36 typename
std::enable_if
<std::is_signed
<T
>::value
, bool>::type
isNonNegative(
42 template<typename T
> inline SAL_CONSTEXPR
43 typename
std::enable_if
<std::is_unsigned
<T
>::value
, bool>::type
isNonNegative(T
)
50 template<typename T
> struct typed_flags
{};
52 /// Mark a (scoped) enumeration as a set of bit flags, with accompanying
56 /// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {};
58 /// All relevant values must be non-negative. (Typically, the enumeration's
59 /// underlying type will either be fixed and unsigned, or it will be unfixed---
60 /// and can thus default to a signed type---and all enumerators will have non-
63 /// \param E the enumeration type.
64 /// \param M the all-bits-set value for the bit flags.
65 template<typename E
, typename
std::underlying_type
<E
>::type M
>
66 struct is_typed_flags
{
68 M
>= 0, "is_typed_flags expects only non-negative bit values");
74 typedef is_typed_flags Unwrapped
;
76 explicit SAL_CONSTEXPR
Wrap(
77 typename
std::underlying_type
<E
>::type value
):
80 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
81 assert(detail::isNonNegative(value
));
83 static_cast<typename
std::underlying_type
<E
>::type
>(~0) == M
84 // avoid "operands don't affect result" warnings when M
85 // covers all bits of the underlying type
86 || (value
& ~M
) == 0);
90 SAL_CONSTEXPR
operator E() const { return static_cast<E
>(value_
); }
92 explicit SAL_CONSTEXPR
operator typename
std::underlying_type
<E
>::type()
96 explicit SAL_CONSTEXPR
operator bool() const { return value_
!= 0; }
99 typename
std::underlying_type
<E
>::type value_
;
102 static typename
std::underlying_type
<E
>::type
const mask
= M
;
108 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator ~(E rhs
) {
109 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
111 o3tl::detail::isNonNegative(
112 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
114 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
115 o3tl::typed_flags
<E
>::mask
116 & ~static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
120 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator ~(
121 typename
o3tl::typed_flags
<E
>::Wrap rhs
)
123 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
124 o3tl::typed_flags
<E
>::mask
125 & ~static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
129 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
132 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
134 o3tl::detail::isNonNegative(
135 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
137 o3tl::detail::isNonNegative(
138 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
140 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
141 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
142 ^ static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
146 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
147 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
149 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
151 o3tl::detail::isNonNegative(
152 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
154 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
155 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
156 ^ static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
160 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
161 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
163 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
165 o3tl::detail::isNonNegative(
166 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
168 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
169 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
170 ^ static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
175 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator ^(
178 return static_cast<W
>(
180 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
183 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
188 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator &(
191 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
193 o3tl::detail::isNonNegative(
194 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
196 o3tl::detail::isNonNegative(
197 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
199 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
200 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
201 & static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
205 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator &(
206 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
208 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
210 o3tl::detail::isNonNegative(
211 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
213 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
214 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
215 & static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
219 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator &(
220 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
222 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
224 o3tl::detail::isNonNegative(
225 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
227 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
228 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
229 & static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
234 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator &(
237 return static_cast<W
>(
239 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
242 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
247 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator |(E lhs
, E rhs
) {
248 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
250 o3tl::detail::isNonNegative(
251 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
253 o3tl::detail::isNonNegative(
254 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
256 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
257 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
258 | static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
262 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator |(
263 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
265 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
267 o3tl::detail::isNonNegative(
268 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
270 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
271 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
272 | static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
276 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<E
>::Wrap
operator |(
277 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
279 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
281 o3tl::detail::isNonNegative(
282 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
284 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
285 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
286 | static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
290 inline SAL_CONSTEXPR typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator |(
293 return static_cast<W
>(
295 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
298 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
303 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(E
& lhs
, E rhs
) {
305 o3tl::detail::isNonNegative(
306 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
308 o3tl::detail::isNonNegative(
309 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
315 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(
316 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
319 o3tl::detail::isNonNegative(
320 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
326 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(E
& lhs
, E rhs
) {
328 o3tl::detail::isNonNegative(
329 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
331 o3tl::detail::isNonNegative(
332 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
338 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(
339 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
342 o3tl::detail::isNonNegative(
343 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
349 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(E
& lhs
, E rhs
) {
351 o3tl::detail::isNonNegative(
352 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
354 o3tl::detail::isNonNegative(
355 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
361 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(
362 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
365 o3tl::detail::isNonNegative(
366 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
371 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */