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>
34 template<typename T
> constexpr
35 typename
std::enable_if
<std::is_signed
<T
>::value
, bool>::type
isNonNegative(
41 template<typename T
> constexpr
42 typename
std::enable_if
<std::is_unsigned
<T
>::value
, bool>::type
isNonNegative(T
)
49 template<typename T
> struct typed_flags
{};
51 /// Mark a (scoped) enumeration as a set of bit flags, with accompanying
55 /// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {};
57 /// All relevant values must be non-negative. (Typically, the enumeration's
58 /// underlying type will either be fixed and unsigned, or it will be unfixed---
59 /// and can thus default to a signed type---and all enumerators will have non-
62 /// \param E the enumeration type.
63 /// \param M the all-bits-set value for the bit flags.
64 template<typename E
, typename
std::underlying_type
<E
>::type M
>
65 struct is_typed_flags
{
67 M
>= 0, "is_typed_flags expects only non-negative bit values");
73 typedef is_typed_flags Unwrapped
;
75 explicit constexpr Wrap(typename
std::underlying_type
<E
>::type value
):
78 assert(detail::isNonNegative(value
));
80 static_cast<typename
std::underlying_type
<E
>::type
>(~0) == M
81 // avoid "operands don't affect result" warnings when M
82 // covers all bits of the underlying type
83 || (value
& ~M
) == 0);
86 constexpr operator E() const { return static_cast<E
>(value_
); }
88 explicit constexpr operator typename
std::underlying_type
<E
>::type()
92 explicit constexpr operator bool() const { return value_
!= 0; }
95 typename
std::underlying_type
<E
>::type value_
;
98 static typename
std::underlying_type
<E
>::type
const mask
= M
;
104 constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ~(E rhs
) {
106 o3tl::detail::isNonNegative(
107 o3tl::to_underlying(rhs
)));
108 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
109 o3tl::typed_flags
<E
>::mask
110 & ~o3tl::to_underlying(rhs
));
113 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ~(
114 typename
o3tl::typed_flags
<E
>::Wrap rhs
)
116 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
117 o3tl::typed_flags
<E
>::mask
118 & ~o3tl::to_underlying
<E
>(rhs
));
121 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
125 o3tl::detail::isNonNegative(
126 o3tl::to_underlying(lhs
)));
128 o3tl::detail::isNonNegative(
129 o3tl::to_underlying(rhs
)));
130 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
131 o3tl::to_underlying(lhs
)
132 ^ o3tl::to_underlying(rhs
));
135 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
136 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
139 o3tl::detail::isNonNegative(
140 o3tl::to_underlying(lhs
)));
141 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
142 o3tl::to_underlying(lhs
)
143 ^ o3tl::to_underlying
<E
>(rhs
));
146 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator ^(
147 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
150 o3tl::detail::isNonNegative(
151 o3tl::to_underlying(rhs
)));
152 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
153 o3tl::to_underlying
<E
>(lhs
)
154 ^ o3tl::to_underlying(rhs
));
157 template<typename W
> constexpr
158 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator ^(
161 return static_cast<W
>(
162 o3tl::to_underlying
<typename
W::Unwrapped::Self
>(lhs
)
163 ^ o3tl::to_underlying
<typename
W::Unwrapped::Self
>(rhs
));
167 constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator &(E lhs
, E rhs
) {
169 o3tl::detail::isNonNegative(
170 o3tl::to_underlying(lhs
)));
172 o3tl::detail::isNonNegative(
173 o3tl::to_underlying(rhs
)));
174 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
175 o3tl::to_underlying(lhs
)
176 & o3tl::to_underlying(rhs
));
179 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator &(
180 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
183 o3tl::detail::isNonNegative(
184 o3tl::to_underlying(lhs
)));
185 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
186 o3tl::to_underlying(lhs
)
187 & o3tl::to_underlying
<E
>(rhs
));
190 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator &(
191 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
194 o3tl::detail::isNonNegative(
195 o3tl::to_underlying(rhs
)));
196 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
197 o3tl::to_underlying
<E
>(lhs
)
198 & o3tl::to_underlying(rhs
));
201 template<typename W
> constexpr
202 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator &(
205 return static_cast<W
>(
206 o3tl::to_underlying
<typename
W::Unwrapped::Self
>(lhs
)
207 & o3tl::to_underlying
<typename
W::Unwrapped::Self
>(rhs
));
211 constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator |(E lhs
, E rhs
) {
213 o3tl::detail::isNonNegative(
214 o3tl::to_underlying(lhs
)));
216 o3tl::detail::isNonNegative(
217 o3tl::to_underlying(rhs
)));
218 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
219 o3tl::to_underlying(lhs
)
220 | o3tl::to_underlying(rhs
));
223 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator |(
224 E lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
227 o3tl::detail::isNonNegative(
228 o3tl::to_underlying(lhs
)));
229 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
230 o3tl::to_underlying(lhs
)
231 | o3tl::to_underlying
<E
>(rhs
));
234 template<typename E
> constexpr typename
o3tl::typed_flags
<E
>::Wrap
operator |(
235 typename
o3tl::typed_flags
<E
>::Wrap lhs
, E rhs
)
238 o3tl::detail::isNonNegative(
239 o3tl::to_underlying(rhs
)));
240 return static_cast<typename
o3tl::typed_flags
<E
>::Wrap
>(
241 o3tl::to_underlying
<E
>(lhs
)
242 | o3tl::to_underlying(rhs
));
245 template<typename W
> constexpr
246 typename
o3tl::typed_flags
<typename
W::Unwrapped::Self
>::Wrap
operator |(
249 return static_cast<W
>(
250 o3tl::to_underlying
<typename
W::Unwrapped::Self
>(lhs
)
251 | o3tl::to_underlying
<typename
W::Unwrapped::Self
>(rhs
));
255 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(E
& lhs
, E rhs
) {
257 o3tl::detail::isNonNegative(
258 o3tl::to_underlying(lhs
)));
260 o3tl::detail::isNonNegative(
261 o3tl::to_underlying(rhs
)));
267 inline typename
o3tl::typed_flags
<E
>::Self
operator &=(
268 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
271 o3tl::detail::isNonNegative(
272 o3tl::to_underlying(lhs
)));
278 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(E
& lhs
, E rhs
) {
280 o3tl::detail::isNonNegative(
281 o3tl::to_underlying(lhs
)));
283 o3tl::detail::isNonNegative(
284 o3tl::to_underlying(rhs
)));
290 inline typename
o3tl::typed_flags
<E
>::Self
operator |=(
291 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
294 o3tl::detail::isNonNegative(
295 o3tl::to_underlying(lhs
)));
301 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(E
& lhs
, E rhs
) {
303 o3tl::detail::isNonNegative(
304 o3tl::to_underlying(lhs
)));
306 o3tl::detail::isNonNegative(
307 o3tl::to_underlying(rhs
)));
313 inline typename
o3tl::typed_flags
<E
>::Self
operator ^=(
314 E
& lhs
, typename
o3tl::typed_flags
<E
>::Wrap rhs
)
317 o3tl::detail::isNonNegative(
318 o3tl::to_underlying(lhs
)));
323 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */