libstdc++
debug/bitset
Go to the documentation of this file.
1 // Debugging bitset implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2025 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file debug/bitset
26  * This file is a GNU debug extension to the Standard C++ Library.
27  */
28 
29 #ifndef _GLIBCXX_DEBUG_BITSET
30 #define _GLIBCXX_DEBUG_BITSET
31 
32 #ifdef _GLIBCXX_SYSHDR
33 #pragma GCC system_header
34 #endif
35 
36 #include <bitset>
37 #include <debug/safe_sequence.h>
38 #include <debug/safe_iterator.h>
39 
40 namespace std _GLIBCXX_VISIBILITY(default)
41 {
42 namespace __debug
43 {
44  /// Class std::bitset with additional safety/checking/debug instrumentation.
45  template<size_t _Nb>
46  class bitset
47  : public _GLIBCXX_STD_C::bitset<_Nb>
48 #if __cplusplus < 201103L
49  , public __gnu_debug::_Safe_sequence_base
50 #endif
51  {
52  typedef _GLIBCXX_STD_C::bitset<_Nb> _Base;
53 
54  public:
55  // In C++11 we rely on normal reference type to preserve the property
56  // of bitset to be use as a literal.
57  // TODO: Find another solution.
58 #if __cplusplus >= 201103L
59  typedef typename _Base::reference reference;
60 #else
61  // bit reference:
62  class reference
63  : private _Base::reference
64  , public __gnu_debug::_Safe_iterator_base
65  {
66  typedef typename _Base::reference _Base_ref;
67 
68  friend class bitset;
69  reference();
70 
71  reference(const _Base_ref& __base, bitset* __seq) _GLIBCXX_NOEXCEPT
72  : _Base_ref(__base)
73  , _Safe_iterator_base(__seq, false)
74  { }
75 
76  public:
77  reference(const reference& __x) _GLIBCXX_NOEXCEPT
78  : _Base_ref(__x)
79  , _Safe_iterator_base(__x, false)
80  { }
81 
82  reference&
83  operator=(bool __x) _GLIBCXX_NOEXCEPT
84  {
85  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
86  _M_message(__gnu_debug::__msg_bad_bitset_write)
87  ._M_iterator(*this));
88  *static_cast<_Base_ref*>(this) = __x;
89  return *this;
90  }
91 
92  reference&
93  operator=(const reference& __x) _GLIBCXX_NOEXCEPT
94  {
95  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
96  _M_message(__gnu_debug::__msg_bad_bitset_read)
97  ._M_iterator(__x));
98  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
99  _M_message(__gnu_debug::__msg_bad_bitset_write)
100  ._M_iterator(*this));
101  *static_cast<_Base_ref*>(this) = __x;
102  return *this;
103  }
104 
105  bool
106  operator~() const _GLIBCXX_NOEXCEPT
107  {
108  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
109  _M_message(__gnu_debug::__msg_bad_bitset_read)
110  ._M_iterator(*this));
111  return ~(*static_cast<const _Base_ref*>(this));
112  }
113 
114  operator bool() const _GLIBCXX_NOEXCEPT
115  {
116  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
117  _M_message(__gnu_debug::__msg_bad_bitset_read)
118  ._M_iterator(*this));
119  return *static_cast<const _Base_ref*>(this);
120  }
121 
122  reference&
123  flip() _GLIBCXX_NOEXCEPT
124  {
125  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
126  _M_message(__gnu_debug::__msg_bad_bitset_flip)
127  ._M_iterator(*this));
128  _Base_ref::flip();
129  return *this;
130  }
131  };
132 #endif
133 
134  // 23.3.5.1 constructors:
135  _GLIBCXX_CONSTEXPR bitset() _GLIBCXX_NOEXCEPT
136  : _Base() { }
137 
138 #if __cplusplus >= 201103L
139  constexpr bitset(unsigned long long __val) noexcept
140 #else
141  bitset(unsigned long __val)
142 #endif
143  : _Base(__val) { }
144 
145  template<typename _CharT, typename _Traits, typename _Alloc>
146  _GLIBCXX23_CONSTEXPR
147  explicit
148  bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
149  typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
150  __pos = 0,
151  typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
152  __n = (std::basic_string<_CharT, _Traits, _Alloc>::npos))
153  : _Base(__str, __pos, __n) { }
154 
155  // _GLIBCXX_RESOLVE_LIB_DEFECTS
156  // 396. what are characters zero and one.
157  template<class _CharT, class _Traits, class _Alloc>
158  _GLIBCXX23_CONSTEXPR
159  bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
160  typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
161  __pos,
162  typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
163  __n,
164  _CharT __zero, _CharT __one = _CharT('1'))
165  : _Base(__str, __pos, __n, __zero, __one) { }
166 
167  _GLIBCXX23_CONSTEXPR
168  bitset(const _Base& __x) : _Base(__x) { }
169 
170 #if __cplusplus >= 201103L
171  template<typename _CharT>
172  _GLIBCXX23_CONSTEXPR
173  explicit
174  bitset(const _CharT* __str,
175  typename std::basic_string<_CharT>::size_type __n
176  = std::basic_string<_CharT>::npos,
177  _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'))
178  : _Base(__str, __n, __zero, __one) { }
179 #endif
180 
181  // 23.3.5.2 bitset operations:
182  _GLIBCXX23_CONSTEXPR
183  bitset<_Nb>&
184  operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
185  {
186  _M_base() &= __rhs;
187  return *this;
188  }
189 
190  _GLIBCXX23_CONSTEXPR
191  bitset<_Nb>&
192  operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
193  {
194  _M_base() |= __rhs;
195  return *this;
196  }
197 
198  _GLIBCXX23_CONSTEXPR
199  bitset<_Nb>&
200  operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
201  {
202  _M_base() ^= __rhs;
203  return *this;
204  }
205 
206  _GLIBCXX23_CONSTEXPR
207  bitset<_Nb>&
208  operator<<=(size_t __pos) _GLIBCXX_NOEXCEPT
209  {
210  _M_base() <<= __pos;
211  return *this;
212  }
213 
214  _GLIBCXX23_CONSTEXPR
215  bitset<_Nb>&
216  operator>>=(size_t __pos) _GLIBCXX_NOEXCEPT
217  {
218  _M_base() >>= __pos;
219  return *this;
220  }
221 
222  _GLIBCXX23_CONSTEXPR
223  bitset<_Nb>&
224  set() _GLIBCXX_NOEXCEPT
225  {
226  _Base::set();
227  return *this;
228  }
229 
230  // _GLIBCXX_RESOLVE_LIB_DEFECTS
231  // 186. bitset::set() second parameter should be bool
232  _GLIBCXX23_CONSTEXPR
233  bitset<_Nb>&
234  set(size_t __pos, bool __val = true)
235  {
236  _Base::set(__pos, __val);
237  return *this;
238  }
239 
240  _GLIBCXX23_CONSTEXPR
241  bitset<_Nb>&
242  reset() _GLIBCXX_NOEXCEPT
243  {
244  _Base::reset();
245  return *this;
246  }
247 
248  _GLIBCXX23_CONSTEXPR
249  bitset<_Nb>&
250  reset(size_t __pos)
251  {
252  _Base::reset(__pos);
253  return *this;
254  }
255 
256  _GLIBCXX23_CONSTEXPR
257  bitset<_Nb>
258  operator~() const _GLIBCXX_NOEXCEPT
259  { return bitset(~_M_base()); }
260 
261  _GLIBCXX23_CONSTEXPR
262  bitset<_Nb>&
263  flip() _GLIBCXX_NOEXCEPT
264  {
265  _Base::flip();
266  return *this;
267  }
268 
269  _GLIBCXX23_CONSTEXPR
270  bitset<_Nb>&
271  flip(size_t __pos)
272  {
273  _Base::flip(__pos);
274  return *this;
275  }
276 
277  // element access:
278  // _GLIBCXX_RESOLVE_LIB_DEFECTS
279  // 11. Bitset minor problems
280  _GLIBCXX23_CONSTEXPR
281  reference
282  operator[](size_t __pos)
283  {
284  __glibcxx_check_subscript(__pos);
285 #if __cplusplus >= 201103L
286  return _M_base()[__pos];
287 #else
288  return reference(_M_base()[__pos], this);
289 #endif
290  }
291 
292  // _GLIBCXX_RESOLVE_LIB_DEFECTS
293  // 11. Bitset minor problems
294  _GLIBCXX_CONSTEXPR bool
295  operator[](size_t __pos) const
296  {
297 #if __cplusplus < 201103L
298  // TODO: Check in debug-mode too.
299  __glibcxx_check_subscript(__pos);
300 #endif
301  return _Base::operator[](__pos);
302  }
303 
304  using _Base::to_ulong;
305 #if __cplusplus >= 201103L
306  using _Base::to_ullong;
307 #endif
308 
309  template <typename _CharT, typename _Traits, typename _Alloc>
310  _GLIBCXX23_CONSTEXPR
311  std::basic_string<_CharT, _Traits, _Alloc>
312  to_string() const
313  { return _M_base().template to_string<_CharT, _Traits, _Alloc>(); }
314 
315  // _GLIBCXX_RESOLVE_LIB_DEFECTS
316  // 396. what are characters zero and one.
317  template<class _CharT, class _Traits, class _Alloc>
318  _GLIBCXX23_CONSTEXPR
319  std::basic_string<_CharT, _Traits, _Alloc>
320  to_string(_CharT __zero, _CharT __one = _CharT('1')) const
321  {
322  return _M_base().template
323  to_string<_CharT, _Traits, _Alloc>(__zero, __one);
324  }
325 
326  // _GLIBCXX_RESOLVE_LIB_DEFECTS
327  // 434. bitset::to_string() hard to use.
328  template<typename _CharT, typename _Traits>
329  _GLIBCXX23_CONSTEXPR
330  std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
331  to_string() const
332  { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); }
333 
334  // _GLIBCXX_RESOLVE_LIB_DEFECTS
335  // 853. to_string needs updating with zero and one.
336  template<class _CharT, class _Traits>
337  _GLIBCXX23_CONSTEXPR
338  std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
339  to_string(_CharT __zero, _CharT __one = _CharT('1')) const
340  { return to_string<_CharT, _Traits,
341  std::allocator<_CharT> >(__zero, __one); }
342 
343  template<typename _CharT>
344  _GLIBCXX23_CONSTEXPR
345  std::basic_string<_CharT, std::char_traits<_CharT>,
346  std::allocator<_CharT> >
347  to_string() const
348  {
349  return to_string<_CharT, std::char_traits<_CharT>,
350  std::allocator<_CharT> >();
351  }
352 
353  template<class _CharT>
354  _GLIBCXX23_CONSTEXPR
355  std::basic_string<_CharT, std::char_traits<_CharT>,
356  std::allocator<_CharT> >
357  to_string(_CharT __zero, _CharT __one = _CharT('1')) const
358  {
359  return to_string<_CharT, std::char_traits<_CharT>,
360  std::allocator<_CharT> >(__zero, __one);
361  }
362 
363  _GLIBCXX23_CONSTEXPR
364  std::basic_string<char, std::char_traits<char>, std::allocator<char> >
365  to_string() const
366  {
367  return to_string<char,std::char_traits<char>,std::allocator<char> >();
368  }
369 
370  _GLIBCXX23_CONSTEXPR
371  std::basic_string<char, std::char_traits<char>, std::allocator<char> >
372  to_string(char __zero, char __one = '1') const
373  {
374  return to_string<char, std::char_traits<char>,
375  std::allocator<char> >(__zero, __one);
376  }
377 
378  using _Base::count;
379  using _Base::size;
380 
381  _GLIBCXX23_CONSTEXPR
382  bool
383  operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
384  { return _M_base() == __rhs._M_base(); }
385 
386 #if __cpp_impl_three_way_comparison < 201907L
387  bool
388  operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
389  { return _M_base() != __rhs._M_base(); }
390 #endif
391 
392  using _Base::test;
393  using _Base::all;
394  using _Base::any;
395  using _Base::none;
396 
397  _GLIBCXX23_CONSTEXPR
398  bitset<_Nb>
399  operator<<(size_t __pos) const _GLIBCXX_NOEXCEPT
400  { return bitset<_Nb>(_M_base() << __pos); }
401 
402  _GLIBCXX23_CONSTEXPR
403  bitset<_Nb>
404  operator>>(size_t __pos) const _GLIBCXX_NOEXCEPT
405  { return bitset<_Nb>(_M_base() >> __pos); }
406 
407  _GLIBCXX23_CONSTEXPR
408  _Base&
409  _M_base() _GLIBCXX_NOEXCEPT
410  { return *this; }
411 
412  _GLIBCXX23_CONSTEXPR
413  const _Base&
414  _M_base() const _GLIBCXX_NOEXCEPT
415  { return *this; }
416  };
417 
418  template<size_t _Nb>
419  _GLIBCXX23_CONSTEXPR
420  inline bitset<_Nb>
421  operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
422  { return bitset<_Nb>(__x) &= __y; }
423 
424  template<size_t _Nb>
425  _GLIBCXX23_CONSTEXPR
426  inline bitset<_Nb>
427  operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
428  { return bitset<_Nb>(__x) |= __y; }
429 
430  template<size_t _Nb>
431  _GLIBCXX23_CONSTEXPR
432  inline bitset<_Nb>
433  operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
434  { return bitset<_Nb>(__x) ^= __y; }
435 
436  template<typename _CharT, typename _Traits, size_t _Nb>
437  inline std::basic_istream<_CharT, _Traits>&
438  operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x)
439  { return __is >> __x._M_base(); }
440 
441  template<typename _CharT, typename _Traits, size_t _Nb>
442  inline std::basic_ostream<_CharT, _Traits>&
443  operator<<(std::basic_ostream<_CharT, _Traits>& __os,
444  const bitset<_Nb>& __x)
445  { return __os << __x._M_base(); }
446 
447 } // namespace __debug
448 
449 #if __cplusplus >= 201103L
450  // DR 1182.
451  /// std::hash specialization for bitset.
452  template<size_t _Nb>
453  struct hash<__debug::bitset<_Nb>>
454  : public __hash_base<size_t, __debug::bitset<_Nb>>
455  {
456  size_t
457  operator()(const __debug::bitset<_Nb>& __b) const noexcept
458  { return std::hash<_GLIBCXX_STD_C::bitset<_Nb>>()(__b._M_base()); }
459  };
460 #endif
461 
462 } // namespace std
463 
464 #endif