LibreOffice Module o3tl (master) 1
typed_flags_set.hxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#ifndef INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
21#define INCLUDED_O3TL_TYPED_FLAGS_SET_HXX
22
23#include <sal/config.h>
24
25#include <cassert>
26#include <type_traits>
27
29
30namespace o3tl {
31
32namespace detail {
33
34template<typename T> constexpr
35typename std::enable_if<std::is_signed<T>::value, bool>::type isNonNegative(
36 T value)
37{
38 return value >= 0;
39}
40
41template<typename T> constexpr
42typename std::enable_if<std::is_unsigned<T>::value, bool>::type isNonNegative(T)
43{
44 return true;
45}
46
47}
48
49template<typename T> struct typed_flags {};
50
64template<typename E, typename std::underlying_type<E>::type M>
66 static_assert(
67 M >= 0, "is_typed_flags expects only non-negative bit values");
68
69 typedef E Self;
70
71 class Wrap {
72 public:
74
75 explicit constexpr Wrap(typename std::underlying_type<E>::type value):
77 {
79 assert(
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);
84 }
85
86 constexpr operator E() const { return static_cast<E>(value_); }
87
88 explicit constexpr operator typename std::underlying_type<E>::type()
89 const
90 { return value_; }
91
92 explicit constexpr operator bool() const { return value_ != 0; }
93
94 private:
95 typename std::underlying_type<E>::type value_;
96 };
97
98 static typename std::underlying_type<E>::type const mask = M;
99};
100
101}
102
103template<typename E>
104constexpr typename o3tl::typed_flags<E>::Wrap operator ~(E rhs) {
105 assert(
107 o3tl::to_underlying(rhs)));
108 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
110 & ~o3tl::to_underlying(rhs));
111}
112
113template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ~(
114 typename o3tl::typed_flags<E>::Wrap rhs)
115{
116 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
118 & ~o3tl::to_underlying<E>(rhs));
119}
120
121template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
122 E lhs, E rhs)
123{
124 assert(
126 o3tl::to_underlying(lhs)));
127 assert(
129 o3tl::to_underlying(rhs)));
130 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
132 ^ o3tl::to_underlying(rhs));
133}
134
135template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
136 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
137{
138 assert(
140 o3tl::to_underlying(lhs)));
141 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
143 ^ o3tl::to_underlying<E>(rhs));
144}
145
146template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
147 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
148{
149 assert(
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));
155}
156
157template<typename W> constexpr
159 W lhs, W rhs)
160{
161 return static_cast<W>(
162 o3tl::to_underlying<typename W::Unwrapped::Self>(lhs)
163 ^ o3tl::to_underlying<typename W::Unwrapped::Self>(rhs));
164}
165
166template<typename E>
167constexpr typename o3tl::typed_flags<E>::Wrap operator &(E lhs, E rhs) {
168 assert(
170 o3tl::to_underlying(lhs)));
171 assert(
173 o3tl::to_underlying(rhs)));
174 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
176 & o3tl::to_underlying(rhs));
177}
178
179template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
180 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
181{
182 assert(
184 o3tl::to_underlying(lhs)));
185 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
187 & o3tl::to_underlying<E>(rhs));
188}
189
190template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
191 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
192{
193 assert(
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));
199}
200
201template<typename W> constexpr
203 W lhs, W rhs)
204{
205 return static_cast<W>(
206 o3tl::to_underlying<typename W::Unwrapped::Self>(lhs)
207 & o3tl::to_underlying<typename W::Unwrapped::Self>(rhs));
208}
209
210template<typename E>
211constexpr typename o3tl::typed_flags<E>::Wrap operator |(E lhs, E rhs) {
212 assert(
214 o3tl::to_underlying(lhs)));
215 assert(
217 o3tl::to_underlying(rhs)));
218 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
220 | o3tl::to_underlying(rhs));
221}
222
223template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
224 E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
225{
226 assert(
228 o3tl::to_underlying(lhs)));
229 return static_cast<typename o3tl::typed_flags<E>::Wrap>(
231 | o3tl::to_underlying<E>(rhs));
232}
233
234template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
235 typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
236{
237 assert(
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));
243}
244
245template<typename W> constexpr
247 W lhs, W rhs)
248{
249 return static_cast<W>(
250 o3tl::to_underlying<typename W::Unwrapped::Self>(lhs)
251 | o3tl::to_underlying<typename W::Unwrapped::Self>(rhs));
252}
253
254template<typename E>
255inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) {
256 assert(
258 o3tl::to_underlying(lhs)));
259 assert(
261 o3tl::to_underlying(rhs)));
262 lhs = lhs & rhs;
263 return lhs;
264}
265
266template<typename E>
268 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
269{
270 assert(
272 o3tl::to_underlying(lhs)));
273 lhs = lhs & rhs;
274 return lhs;
275}
276
277template<typename E>
278inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) {
279 assert(
281 o3tl::to_underlying(lhs)));
282 assert(
284 o3tl::to_underlying(rhs)));
285 lhs = lhs | rhs;
286 return lhs;
287}
288
289template<typename E>
291 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
292{
293 assert(
295 o3tl::to_underlying(lhs)));
296 lhs = lhs | rhs;
297 return lhs;
298}
299
300template<typename E>
301inline typename o3tl::typed_flags<E>::Self operator ^=(E & lhs, E rhs) {
302 assert(
304 o3tl::to_underlying(lhs)));
305 assert(
307 o3tl::to_underlying(rhs)));
308 lhs = lhs ^ rhs;
309 return lhs;
310}
311
312template<typename E>
314 E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
315{
316 assert(
318 o3tl::to_underlying(lhs)));
319 lhs = lhs ^ rhs;
320 return lhs;
321}
322
323#endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
324
325/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::underlying_type< E >::type value_
constexpr Wrap(typename std::underlying_type< E >::type value)
Any value
constexpr std::enable_if< std::is_signed< T >::value, bool >::type isNonNegative(T value)
constexpr std::underlying_type_t< T > to_underlying(T e)
M
Mark a (scoped) enumeration as a set of bit flags, with accompanying operations.
static std::underlying_type< E >::type const mask
constexpr o3tl::typed_flags< E >::Wrap operator^(E lhs, E rhs)
constexpr o3tl::typed_flags< E >::Wrap operator&(E lhs, E rhs)
constexpr o3tl::typed_flags< E >::Wrap operator|(E lhs, E rhs)
o3tl::typed_flags< E >::Self operator^=(E &lhs, E rhs)
o3tl::typed_flags< E >::Self operator|=(E &lhs, E rhs)
o3tl::typed_flags< E >::Self operator&=(E &lhs, E rhs)
constexpr o3tl::typed_flags< E >::Wrap operator~(E rhs)