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 #include <sal/types.h>
30 
31 namespace o3tl {
32 
33 namespace detail {
34 
35 template<typename T> constexpr
36 typename std::enable_if<std::is_signed<T>::value, bool>::type isNonNegative(
37  T value)
38 {
39  return value >= 0;
40 }
41 
42 template<typename T> constexpr
43 typename std::enable_if<std::is_unsigned<T>::value, bool>::type isNonNegative(T)
44 {
45  return true;
46 }
47 
48 }
49 
50 template<typename T> struct typed_flags {};
51 
65 template<typename E, typename std::underlying_type<E>::type M>
67  static_assert(
68  M >= 0, "is_typed_flags expects only non-negative bit values");
69 
70  typedef E Self;
71 
72  class Wrap {
73  public:
75 
76  explicit constexpr Wrap(typename std::underlying_type<E>::type value):
77  value_(value)
78  {
79  assert(detail::isNonNegative(value));
80  assert(
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);
85  }
86 
87  constexpr operator E() const { return static_cast<E>(value_); }
88 
89  explicit constexpr operator typename std::underlying_type<E>::type()
90  const
91  { return value_; }
92 
93  explicit constexpr operator bool() const { return value_ != 0; }
94 
95  private:
96  typename std::underlying_type<E>::type value_;
97  };
98 
99  static typename std::underlying_type<E>::type const mask = M;
100 };
101 
102 }
103 
104 template<typename E>
105 constexpr typename o3tl::typed_flags<E>::Wrap operator ~(E rhs) {
106  assert(
109  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
111  & ~o3tl::underlyingEnumValue(rhs));
112 }
113 
114 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ~(
115  typename o3tl::typed_flags<E>::Wrap rhs)
116 {
117  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
119  & ~o3tl::underlyingEnumValue<E>(rhs));
120 }
121 
122 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
123  E lhs, E rhs)
124 {
125  assert(
128  assert(
131  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
134 }
135 
136 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
137  E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
138 {
139  assert(
142  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
144  ^ o3tl::underlyingEnumValue<E>(rhs));
145 }
146 
147 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator ^(
148  typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
149 {
150  assert(
153  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
154  o3tl::underlyingEnumValue<E>(lhs)
156 }
157 
158 template<typename W> constexpr
160  W lhs, W rhs)
161 {
162  return static_cast<W>(
163  o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs)
164  ^ o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs));
165 }
166 
167 template<typename E>
168 constexpr typename o3tl::typed_flags<E>::Wrap operator &(E lhs, E rhs) {
169  assert(
172  assert(
175  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
178 }
179 
180 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
181  E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
182 {
183  assert(
186  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
188  & o3tl::underlyingEnumValue<E>(rhs));
189 }
190 
191 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator &(
192  typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
193 {
194  assert(
197  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
198  o3tl::underlyingEnumValue<E>(lhs)
200 }
201 
202 template<typename W> constexpr
204  W lhs, W rhs)
205 {
206  return static_cast<W>(
207  o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs)
208  & o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs));
209 }
210 
211 template<typename E>
212 constexpr typename o3tl::typed_flags<E>::Wrap operator |(E lhs, E rhs) {
213  assert(
216  assert(
219  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
222 }
223 
224 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
225  E lhs, typename o3tl::typed_flags<E>::Wrap rhs)
226 {
227  assert(
230  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
232  | o3tl::underlyingEnumValue<E>(rhs));
233 }
234 
235 template<typename E> constexpr typename o3tl::typed_flags<E>::Wrap operator |(
236  typename o3tl::typed_flags<E>::Wrap lhs, E rhs)
237 {
238  assert(
241  return static_cast<typename o3tl::typed_flags<E>::Wrap>(
242  o3tl::underlyingEnumValue<E>(lhs)
244 }
245 
246 template<typename W> constexpr
248  W lhs, W rhs)
249 {
250  return static_cast<W>(
251  o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(lhs)
252  | o3tl::underlyingEnumValue<typename W::Unwrapped::Self>(rhs));
253 }
254 
255 template<typename E>
256 inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) {
257  assert(
260  assert(
263  lhs = lhs & rhs;
264  return lhs;
265 }
266 
267 template<typename E>
269  E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
270 {
271  assert(
274  lhs = lhs & rhs;
275  return lhs;
276 }
277 
278 template<typename E>
279 inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) {
280  assert(
283  assert(
286  lhs = lhs | rhs;
287  return lhs;
288 }
289 
290 template<typename E>
292  E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
293 {
294  assert(
297  lhs = lhs | rhs;
298  return lhs;
299 }
300 
301 template<typename E>
302 inline typename o3tl::typed_flags<E>::Self operator ^=(E & lhs, E rhs) {
303  assert(
306  assert(
309  lhs = lhs ^ rhs;
310  return lhs;
311 }
312 
313 template<typename E>
315  E & lhs, typename o3tl::typed_flags<E>::Wrap rhs)
316 {
317  assert(
320  lhs = lhs ^ rhs;
321  return lhs;
322 }
323 
324 #endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */
325 
326 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
o3tl::typed_flags< E >::Self operator&=(E &lhs, E rhs)
constexpr std::underlying_type_t< T > underlyingEnumValue(T e)
constexpr o3tl::typed_flags< E >::Wrap operator|(E lhs, E rhs)
constexpr o3tl::typed_flags< E >::Wrap operator~(E rhs)
constexpr Wrap(typename std::underlying_type< E >::type value)
std::underlying_type< E >::type value_
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)
Mark a (scoped) enumeration as a set of bit flags, with accompanying operations.
static std::underlying_type< E >::type const mask
o3tl::typed_flags< E >::Self operator|=(E &lhs, E rhs)
M
constexpr std::enable_if< std::is_signed< T >::value, bool >::type isNonNegative(T value)