build fix
[LibreOffice.git] / include / o3tl / typed_flags_set.hxx
blob637fcfa6c3ff865cd5cb6f7b6fecfb3fb0dc0a73
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> inline SAL_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> inline SAL_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 SAL_CONSTEXPR Wrap(
77 typename std::underlying_type<E>::type value):
78 value_(value)
80 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
81 assert(detail::isNonNegative(value));
82 assert(
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);
87 #endif
90 SAL_CONSTEXPR operator E() const { return static_cast<E>(value_); }
92 explicit SAL_CONSTEXPR operator typename std::underlying_type<E>::type()
93 const
94 { return value_; }
96 explicit SAL_CONSTEXPR operator bool() const { return value_ != 0; }
98 private:
99 typename std::underlying_type<E>::type value_;
102 static typename std::underlying_type<E>::type const mask = M;
107 template<typename E>
108 inline SAL_CONSTEXPR typename o3tl::typed_flags<E>::Wrap operator ~(E rhs) {
109 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
110 assert(
111 o3tl::detail::isNonNegative(
112 static_cast<typename std::underlying_type<E>::type>(rhs)));
113 #endif
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));
119 template<typename E>
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));
128 template<typename E>
129 inline SAL_CONSTEXPR typename o3tl::typed_flags<E>::Wrap operator ^(
130 E lhs, E rhs)
132 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
133 assert(
134 o3tl::detail::isNonNegative(
135 static_cast<typename std::underlying_type<E>::type>(lhs)));
136 assert(
137 o3tl::detail::isNonNegative(
138 static_cast<typename std::underlying_type<E>::type>(rhs)));
139 #endif
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));
145 template<typename E>
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
150 assert(
151 o3tl::detail::isNonNegative(
152 static_cast<typename std::underlying_type<E>::type>(lhs)));
153 #endif
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));
159 template<typename E>
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
164 assert(
165 o3tl::detail::isNonNegative(
166 static_cast<typename std::underlying_type<E>::type>(rhs)));
167 #endif
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));
173 template<typename W>
174 inline SAL_CONSTEXPR
175 typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator ^(
176 W lhs, W rhs)
178 return static_cast<W>(
179 static_cast<
180 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
181 lhs)
182 ^ static_cast<
183 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
184 rhs));
187 template<typename E>
188 inline SAL_CONSTEXPR typename o3tl::typed_flags<E>::Wrap operator &(
189 E lhs, E rhs)
191 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
192 assert(
193 o3tl::detail::isNonNegative(
194 static_cast<typename std::underlying_type<E>::type>(lhs)));
195 assert(
196 o3tl::detail::isNonNegative(
197 static_cast<typename std::underlying_type<E>::type>(rhs)));
198 #endif
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));
204 template<typename E>
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
209 assert(
210 o3tl::detail::isNonNegative(
211 static_cast<typename std::underlying_type<E>::type>(lhs)));
212 #endif
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));
218 template<typename E>
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
223 assert(
224 o3tl::detail::isNonNegative(
225 static_cast<typename std::underlying_type<E>::type>(rhs)));
226 #endif
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));
232 template<typename W>
233 inline SAL_CONSTEXPR
234 typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator &(
235 W lhs, W rhs)
237 return static_cast<W>(
238 static_cast<
239 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
240 lhs)
241 & static_cast<
242 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
243 rhs));
246 template<typename E>
247 inline SAL_CONSTEXPR typename o3tl::typed_flags<E>::Wrap operator |(E lhs, E rhs) {
248 #if !HAVE_CXX11_CONSTEXPR || HAVE_CXX14_CONSTEXPR
249 assert(
250 o3tl::detail::isNonNegative(
251 static_cast<typename std::underlying_type<E>::type>(lhs)));
252 assert(
253 o3tl::detail::isNonNegative(
254 static_cast<typename std::underlying_type<E>::type>(rhs)));
255 #endif
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));
261 template<typename E>
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
266 assert(
267 o3tl::detail::isNonNegative(
268 static_cast<typename std::underlying_type<E>::type>(lhs)));
269 #endif
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));
275 template<typename E>
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
280 assert(
281 o3tl::detail::isNonNegative(
282 static_cast<typename std::underlying_type<E>::type>(rhs)));
283 #endif
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));
289 template<typename W>
290 inline SAL_CONSTEXPR typename o3tl::typed_flags<typename W::Unwrapped::Self>::Wrap operator |(
291 W lhs, W rhs)
293 return static_cast<W>(
294 static_cast<
295 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
296 lhs)
297 | static_cast<
298 typename std::underlying_type<typename W::Unwrapped::Self>::type>(
299 rhs));
302 template<typename E>
303 inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) {
304 assert(
305 o3tl::detail::isNonNegative(
306 static_cast<typename std::underlying_type<E>::type>(lhs)));
307 assert(
308 o3tl::detail::isNonNegative(
309 static_cast<typename std::underlying_type<E>::type>(rhs)));
310 lhs = lhs & rhs;
311 return lhs;
314 template<typename E>
315 inline typename o3tl::typed_flags<E>::Self operator &=(
316 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
318 assert(
319 o3tl::detail::isNonNegative(
320 static_cast<typename std::underlying_type<E>::type>(lhs)));
321 lhs = lhs & rhs;
322 return lhs;
325 template<typename E>
326 inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) {
327 assert(
328 o3tl::detail::isNonNegative(
329 static_cast<typename std::underlying_type<E>::type>(lhs)));
330 assert(
331 o3tl::detail::isNonNegative(
332 static_cast<typename std::underlying_type<E>::type>(rhs)));
333 lhs = lhs | rhs;
334 return lhs;
337 template<typename E>
338 inline typename o3tl::typed_flags<E>::Self operator |=(
339 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
341 assert(
342 o3tl::detail::isNonNegative(
343 static_cast<typename std::underlying_type<E>::type>(lhs)));
344 lhs = lhs | rhs;
345 return lhs;
348 template<typename E>
349 inline typename o3tl::typed_flags<E>::Self operator ^=(E & lhs, E rhs) {
350 assert(
351 o3tl::detail::isNonNegative(
352 static_cast<typename std::underlying_type<E>::type>(lhs)));
353 assert(
354 o3tl::detail::isNonNegative(
355 static_cast<typename std::underlying_type<E>::type>(rhs)));
356 lhs = lhs ^ rhs;
357 return lhs;
360 template<typename E>
361 inline typename o3tl::typed_flags<E>::Self operator ^=(
362 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
364 assert(
365 o3tl::detail::isNonNegative(
366 static_cast<typename std::underlying_type<E>::type>(lhs)));
367 lhs = lhs ^ rhs;
368 return lhs;
371 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
373 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */