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
> constexpr
36 typename
std::enable_if
<std::is_signed
<T
>::value
, bool>::type
isNonNegative(
42 template<typename T
> 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 constexpr Wrap(typename
std::underlying_type
<E
>::type value
):
79 #if HAVE_CXX14_CONSTEXPR
80 assert(detail::isNonNegative(value
));
82 static_cast<typename
std::underlying_type
<E
>::type
>(~0) == M
83 // avoid "operands don't affect result" warnings when M
84 // covers all bits of the underlying type
85 || (value
& ~M
) == 0);
89 constexpr operator E() const { return static_cast<E
>(value_
); }
91 explicit constexpr operator typename
std::underlying_type
<E
>::type()
95 explicit constexpr operator bool() const { return value_
!= 0; }
98 typename
std::underlying_type
<E
>::type value_
;
101 static typename
std::underlying_type
<E
>::type
const mask
= M
;
107 constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ~(E rhs
) {
108 #if HAVE_CXX14_CONSTEXPR
110 o3tl::detail::isNonNegative(
111 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
113 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
114 o3tl::typed_flags
<E
>::mask
115 & ~static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
118 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ~(
119 typename
o3tl::typed_flags
<E
>::Wrap rhs
)
121 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
122 o3tl::typed_flags
<E
>::mask
123 & ~static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
126 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
129 #if HAVE_CXX14_CONSTEXPR
131 o3tl::detail::isNonNegative(
132 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
134 o3tl::detail::isNonNegative(
135 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
137 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
138 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
139 ^ static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
142 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
143 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
145 #if HAVE_CXX14_CONSTEXPR
147 o3tl::detail::isNonNegative(
148 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
150 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
151 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
152 ^ static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
155 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
156 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
158 #if HAVE_CXX14_CONSTEXPR
160 o3tl::detail::isNonNegative(
161 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
163 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
164 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
165 ^ static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
168 template<typename W
> constexpr
169 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator ^(
172 return static_cast<W
>(
174 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
177 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
182 constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator &(E lhs
, E rhs
) {
183 #if HAVE_CXX14_CONSTEXPR
185 o3tl::detail::isNonNegative(
186 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
188 o3tl::detail::isNonNegative(
189 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
191 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
192 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
193 & static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
196 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator &(
197 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
199 #if HAVE_CXX14_CONSTEXPR
201 o3tl::detail::isNonNegative(
202 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
204 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
205 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
206 & static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
209 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator &(
210 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
212 #if HAVE_CXX14_CONSTEXPR
214 o3tl::detail::isNonNegative(
215 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
217 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
218 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
219 & static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
222 template<typename W
> constexpr
223 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator &(
226 return static_cast<W
>(
228 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
231 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
236 constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator |(E lhs
, E rhs
) {
237 #if HAVE_CXX14_CONSTEXPR
239 o3tl::detail::isNonNegative(
240 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
242 o3tl::detail::isNonNegative(
243 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
245 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
246 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
247 | static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
250 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator |(
251 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
253 #if HAVE_CXX14_CONSTEXPR
255 o3tl::detail::isNonNegative(
256 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
258 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
259 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
260 | static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
263 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator |(
264 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
266 #if HAVE_CXX14_CONSTEXPR
268 o3tl::detail::isNonNegative(
269 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
271 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
272 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)
273 | static_cast<typename
std::underlying_type
<E
>::type
>(rhs
));
276 template<typename W
> constexpr
277 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator |(
280 return static_cast<W
>(
282 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
285 typename
std::underlying_type
<typename
W::Unwrapped::Self
>::type
>(
290 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(E
& lhs
, E rhs
) {
292 o3tl::detail::isNonNegative(
293 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
295 o3tl::detail::isNonNegative(
296 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
302 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(
303 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
306 o3tl::detail::isNonNegative(
307 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
313 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(E
& lhs
, E rhs
) {
315 o3tl::detail::isNonNegative(
316 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
318 o3tl::detail::isNonNegative(
319 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
325 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(
326 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
329 o3tl::detail::isNonNegative(
330 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
336 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(E
& lhs
, E rhs
) {
338 o3tl::detail::isNonNegative(
339 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
341 o3tl::detail::isNonNegative(
342 static_cast<typename
std::underlying_type
<E
>::type
>(rhs
)));
348 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(
349 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
352 o3tl::detail::isNonNegative(
353 static_cast<typename
std::underlying_type
<E
>::type
>(lhs
)));
358 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */