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 <o3tl/underlyingenumvalue.hxx>
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 assert(detail::isNonNegative(value
));
81 static_cast<typename
std::underlying_type
<E
>::type
>(~0) == M
82 // avoid "operands don't affect result" warnings when M
83 // covers all bits of the underlying type
84 || (value
& ~M
) == 0);
87 constexpr operator E() const { return static_cast<E
>(value_
); }
89 explicit constexpr operator typename
std::underlying_type
<E
>::type()
93 explicit constexpr operator bool() const { return value_
!= 0; }
96 typename
std::underlying_type
<E
>::type value_
;
99 static typename
std::underlying_type
<E
>::type
const mask
= M
;
105 constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ~(E rhs
) {
107 o3tl::detail::isNonNegative(
108 o3tl::underlyingEnumValue(rhs
)));
109 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
110 o3tl::typed_flags
<E
>::mask
111 & ~o3tl::underlyingEnumValue(rhs
));
114 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ~(
115 typename
o3tl::typed_flags
<E
>::Wrap rhs
)
117 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
118 o3tl::typed_flags
<E
>::mask
119 & ~o3tl::underlyingEnumValue
<E
>(rhs
));
122 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
126 o3tl::detail::isNonNegative(
127 o3tl::underlyingEnumValue(lhs
)));
129 o3tl::detail::isNonNegative(
130 o3tl::underlyingEnumValue(rhs
)));
131 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
132 o3tl::underlyingEnumValue(lhs
)
133 ^ o3tl::underlyingEnumValue(rhs
));
136 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
137 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
140 o3tl::detail::isNonNegative(
141 o3tl::underlyingEnumValue(lhs
)));
142 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
143 o3tl::underlyingEnumValue(lhs
)
144 ^ o3tl::underlyingEnumValue
<E
>(rhs
));
147 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
148 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
151 o3tl::detail::isNonNegative(
152 o3tl::underlyingEnumValue(rhs
)));
153 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
154 o3tl::underlyingEnumValue
<E
>(lhs
)
155 ^ o3tl::underlyingEnumValue(rhs
));
158 template<typename W
> constexpr
159 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator ^(
162 return static_cast<W
>(
163 o3tl::underlyingEnumValue
<typename
W::Unwrapped::Self
>(lhs
)
164 ^ o3tl::underlyingEnumValue
<typename
W::Unwrapped::Self
>(rhs
));
168 constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator &(E lhs
, E rhs
) {
170 o3tl::detail::isNonNegative(
171 o3tl::underlyingEnumValue(lhs
)));
173 o3tl::detail::isNonNegative(
174 o3tl::underlyingEnumValue(rhs
)));
175 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
176 o3tl::underlyingEnumValue(lhs
)
177 & o3tl::underlyingEnumValue(rhs
));
180 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator &(
181 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
184 o3tl::detail::isNonNegative(
185 o3tl::underlyingEnumValue(lhs
)));
186 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
187 o3tl::underlyingEnumValue(lhs
)
188 & o3tl::underlyingEnumValue
<E
>(rhs
));
191 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator &(
192 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
195 o3tl::detail::isNonNegative(
196 o3tl::underlyingEnumValue(rhs
)));
197 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
198 o3tl::underlyingEnumValue
<E
>(lhs
)
199 & o3tl::underlyingEnumValue(rhs
));
202 template<typename W
> constexpr
203 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator &(
206 return static_cast<W
>(
207 o3tl::underlyingEnumValue
<typename
W::Unwrapped::Self
>(lhs
)
208 & o3tl::underlyingEnumValue
<typename
W::Unwrapped::Self
>(rhs
));
212 constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator |(E lhs
, E rhs
) {
214 o3tl::detail::isNonNegative(
215 o3tl::underlyingEnumValue(lhs
)));
217 o3tl::detail::isNonNegative(
218 o3tl::underlyingEnumValue(rhs
)));
219 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
220 o3tl::underlyingEnumValue(lhs
)
221 | o3tl::underlyingEnumValue(rhs
));
224 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator |(
225 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
228 o3tl::detail::isNonNegative(
229 o3tl::underlyingEnumValue(lhs
)));
230 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
231 o3tl::underlyingEnumValue(lhs
)
232 | o3tl::underlyingEnumValue
<E
>(rhs
));
235 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator |(
236 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
239 o3tl::detail::isNonNegative(
240 o3tl::underlyingEnumValue(rhs
)));
241 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
242 o3tl::underlyingEnumValue
<E
>(lhs
)
243 | o3tl::underlyingEnumValue(rhs
));
246 template<typename W
> constexpr
247 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator |(
250 return static_cast<W
>(
251 o3tl::underlyingEnumValue
<typename
W::Unwrapped::Self
>(lhs
)
252 | o3tl::underlyingEnumValue
<typename
W::Unwrapped::Self
>(rhs
));
256 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(E
& lhs
, E rhs
) {
258 o3tl::detail::isNonNegative(
259 o3tl::underlyingEnumValue(lhs
)));
261 o3tl::detail::isNonNegative(
262 o3tl::underlyingEnumValue(rhs
)));
268 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(
269 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
272 o3tl::detail::isNonNegative(
273 o3tl::underlyingEnumValue(lhs
)));
279 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(E
& lhs
, E rhs
) {
281 o3tl::detail::isNonNegative(
282 o3tl::underlyingEnumValue(lhs
)));
284 o3tl::detail::isNonNegative(
285 o3tl::underlyingEnumValue(rhs
)));
291 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(
292 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
295 o3tl::detail::isNonNegative(
296 o3tl::underlyingEnumValue(lhs
)));
302 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(E
& lhs
, E rhs
) {
304 o3tl::detail::isNonNegative(
305 o3tl::underlyingEnumValue(lhs
)));
307 o3tl::detail::isNonNegative(
308 o3tl::underlyingEnumValue(rhs
)));
314 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(
315 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
318 o3tl::detail::isNonNegative(
319 o3tl::underlyingEnumValue(lhs
)));
324 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
326 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */