Version 5.4.3.2, tag libreoffice-5.4.3.2
[LibreOffice.git] / include / o3tl / typed_flags_set.hxx
blob09f0b61d8c01a4a53f58baf33b8721a324672b56
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
25 #include <cassert>
26 #include <type_traits>
28 #include <config_global.h>
29 #include <sal/types.h>
31 namespace o3tl {
33 namespace detail {
35 template<typename T> constexpr
36 typename std::enable_if<std::is_signed<T>::value, bool>::type isNonNegative(
37 T value)
39 return value >= 0;
42 template<typename T> constexpr
43 typename std::enable_if<std::is_unsigned<T>::value, bool>::type isNonNegative(T)
45 return true;
50 template<typename T> struct typed_flags {};
52 /// Mark a (scoped) enumeration as a set of bit flags, with accompanying
53 /// operations.
54 ///
55 /// template<>
56 /// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {};
57 ///
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-
61 /// negative values.)
62 ///
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 {
67 static_assert(
68 M >= 0, "is_typed_flags expects only non-negative bit values");
70 typedef E Self;
72 class Wrap {
73 public:
74 typedef is_typed_flags Unwrapped;
76 explicit constexpr Wrap(typename std::underlying_type<E>::type value):
77 value_(value)
79 #if HAVE_CXX14_CONSTEXPR
80 assert(detail::isNonNegative(value));
81 assert(
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);
86 #endif
89 constexpr operator E() const { return static_cast<E>(value_); }
91 explicit constexpr operator typename std::underlying_type<E>::type()
92 const
93 { return value_; }
95 explicit constexpr operator bool() const { return value_ != 0; }
97 private:
98 typename std::underlying_type<E>::type value_;
101 static typename std::underlying_type<E>::type const mask = M;
106 template<typename E>
107 constexpr typename o3tl::typed_flags<E>::Wrap operator ~(E rhs) {
108 #if HAVE_CXX14_CONSTEXPR
109 assert(
110 o3tl::detail::isNonNegative(
111 static_cast<typename std::underlying_type<E>::type>(rhs)));
112 #endif
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 ^(
127 E lhs, E rhs)
129 #if HAVE_CXX14_CONSTEXPR
130 assert(
131 o3tl::detail::isNonNegative(
132 static_cast<typename std::underlying_type<E>::type>(lhs)));
133 assert(
134 o3tl::detail::isNonNegative(
135 static_cast<typename std::underlying_type<E>::type>(rhs)));
136 #endif
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
146 assert(
147 o3tl::detail::isNonNegative(
148 static_cast<typename std::underlying_type<E>::type>(lhs)));
149 #endif
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
159 assert(
160 o3tl::detail::isNonNegative(
161 static_cast<typename std::underlying_type<E>::type>(rhs)));
162 #endif
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 ^(
170 W lhs, W rhs)
172 return static_cast<W>(
173 static_cast<
174 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
175 lhs)
176 ^ static_cast<
177 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
178 rhs));
181 template<typename E>
182 constexpr typename o3tl::typed_flags<E>::Wrap operator &(E lhs, E rhs) {
183 #if HAVE_CXX14_CONSTEXPR
184 assert(
185 o3tl::detail::isNonNegative(
186 static_cast<typename std::underlying_type<E>::type>(lhs)));
187 assert(
188 o3tl::detail::isNonNegative(
189 static_cast<typename std::underlying_type<E>::type>(rhs)));
190 #endif
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
200 assert(
201 o3tl::detail::isNonNegative(
202 static_cast<typename std::underlying_type<E>::type>(lhs)));
203 #endif
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
213 assert(
214 o3tl::detail::isNonNegative(
215 static_cast<typename std::underlying_type<E>::type>(rhs)));
216 #endif
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 &(
224 W lhs, W rhs)
226 return static_cast<W>(
227 static_cast<
228 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
229 lhs)
230 & static_cast<
231 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
232 rhs));
235 template<typename E>
236 constexpr typename o3tl::typed_flags<E>::Wrap operator |(E lhs, E rhs) {
237 #if HAVE_CXX14_CONSTEXPR
238 assert(
239 o3tl::detail::isNonNegative(
240 static_cast<typename std::underlying_type<E>::type>(lhs)));
241 assert(
242 o3tl::detail::isNonNegative(
243 static_cast<typename std::underlying_type<E>::type>(rhs)));
244 #endif
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
254 assert(
255 o3tl::detail::isNonNegative(
256 static_cast<typename std::underlying_type<E>::type>(lhs)));
257 #endif
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
267 assert(
268 o3tl::detail::isNonNegative(
269 static_cast<typename std::underlying_type<E>::type>(rhs)));
270 #endif
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 |(
278 W lhs, W rhs)
280 return static_cast<W>(
281 static_cast<
282 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
283 lhs)
284 | static_cast<
285 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
286 rhs));
289 template<typename E>
290 inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) {
291 assert(
292 o3tl::detail::isNonNegative(
293 static_cast<typename std::underlying_type<E>::type>(lhs)));
294 assert(
295 o3tl::detail::isNonNegative(
296 static_cast<typename std::underlying_type<E>::type>(rhs)));
297 lhs = lhs & rhs;
298 return lhs;
301 template<typename E>
302 inline typename o3tl::typed_flags<E>::Self operator &=(
303 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
305 assert(
306 o3tl::detail::isNonNegative(
307 static_cast<typename std::underlying_type<E>::type>(lhs)));
308 lhs = lhs & rhs;
309 return lhs;
312 template<typename E>
313 inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) {
314 assert(
315 o3tl::detail::isNonNegative(
316 static_cast<typename std::underlying_type<E>::type>(lhs)));
317 assert(
318 o3tl::detail::isNonNegative(
319 static_cast<typename std::underlying_type<E>::type>(rhs)));
320 lhs = lhs | rhs;
321 return lhs;
324 template<typename E>
325 inline typename o3tl::typed_flags<E>::Self operator |=(
326 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
328 assert(
329 o3tl::detail::isNonNegative(
330 static_cast<typename std::underlying_type<E>::type>(lhs)));
331 lhs = lhs | rhs;
332 return lhs;
335 template<typename E>
336 inline typename o3tl::typed_flags<E>::Self operator ^=(E & lhs, E rhs) {
337 assert(
338 o3tl::detail::isNonNegative(
339 static_cast<typename std::underlying_type<E>::type>(lhs)));
340 assert(
341 o3tl::detail::isNonNegative(
342 static_cast<typename std::underlying_type<E>::type>(rhs)));
343 lhs = lhs ^ rhs;
344 return lhs;
347 template<typename E>
348 inline typename o3tl::typed_flags<E>::Self operator ^=(
349 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
351 assert(
352 o3tl::detail::isNonNegative(
353 static_cast<typename std::underlying_type<E>::type>(lhs)));
354 lhs = lhs ^ rhs;
355 return lhs;
358 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */