libstdc++
debug/bitset
Go to the documentation of this file.
1 // Debugging bitset implementation -*- C++ -*-
2 
3 // Copyright (C) 2003-2022 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 #pragma GCC system_header
33 
34 #include <bitset>
35 #include <debug/safe_sequence.h>
36 #include <debug/safe_iterator.h>
37 
38 namespace std _GLIBCXX_VISIBILITY(default)
39 {
40 namespace __debug
41 {
42  /// Class std::bitset with additional safety/checking/debug instrumentation.
43  template<size_t _Nb>
44  class bitset
45  : public _GLIBCXX_STD_C::bitset<_Nb>
46 #if __cplusplus < 201103L
47  , public __gnu_debug::_Safe_sequence_base
48 #endif
49  {
50  typedef _GLIBCXX_STD_C::bitset<_Nb> _Base;
51 
52  public:
53  // In C++11 we rely on normal reference type to preserve the property
54  // of bitset to be use as a literal.
55  // TODO: Find another solution.
56 #if __cplusplus >= 201103L
57  typedef typename _Base::reference reference;
58 #else
59  // bit reference:
60  class reference
61  : private _Base::reference
62  , public __gnu_debug::_Safe_iterator_base
63  {
64  typedef typename _Base::reference _Base_ref;
65 
66  friend class bitset;
67  reference();
68 
69  reference(const _Base_ref& __base, bitset* __seq) _GLIBCXX_NOEXCEPT
70  : _Base_ref(__base)
71  , _Safe_iterator_base(__seq, false)
72  { }
73 
74  public:
75  reference(const reference& __x) _GLIBCXX_NOEXCEPT
76  : _Base_ref(__x)
77  , _Safe_iterator_base(__x, false)
78  { }
79 
80  reference&
81  operator=(bool __x) _GLIBCXX_NOEXCEPT
82  {
83  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
84  _M_message(__gnu_debug::__msg_bad_bitset_write)
85  ._M_iterator(*this));
86  *static_cast<_Base_ref*>(this) = __x;
87  return *this;
88  }
89 
90  reference&
91  operator=(const reference& __x) _GLIBCXX_NOEXCEPT
92  {
93  _GLIBCXX_DEBUG_VERIFY(!__x._M_singular(),
94  _M_message(__gnu_debug::__msg_bad_bitset_read)
95  ._M_iterator(__x));
96  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
97  _M_message(__gnu_debug::__msg_bad_bitset_write)
98  ._M_iterator(*this));
99  *static_cast<_Base_ref*>(this) = __x;
100  return *this;
101  }
102 
103  bool
104  operator~() const _GLIBCXX_NOEXCEPT
105  {
106  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
107  _M_message(__gnu_debug::__msg_bad_bitset_read)
108  ._M_iterator(*this));
109  return ~(*static_cast<const _Base_ref*>(this));
110  }
111 
112  operator bool() const _GLIBCXX_NOEXCEPT
113  {
114  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
115  _M_message(__gnu_debug::__msg_bad_bitset_read)
116  ._M_iterator(*this));
117  return *static_cast<const _Base_ref*>(this);
118  }
119 
120  reference&
121  flip() _GLIBCXX_NOEXCEPT
122  {
123  _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(),
124  _M_message(__gnu_debug::__msg_bad_bitset_flip)
125  ._M_iterator(*this));
126  _Base_ref::flip();
127  return *this;
128  }
129  };
130 #endif
131 
132  // 23.3.5.1 constructors:
133  _GLIBCXX_CONSTEXPR bitset() _GLIBCXX_NOEXCEPT
134  : _Base() { }
135 
136 #if __cplusplus >= 201103L
137  constexpr bitset(unsigned long long __val) noexcept
138 #else
139  bitset(unsigned long __val)
140 #endif
141  : _Base(__val) { }
142 
143  template<typename _CharT, typename _Traits, typename _Alloc>
144  explicit
145  bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
146  typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
147  __pos = 0,
148  typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
149  __n = (std::basic_string<_CharT, _Traits, _Alloc>::npos))
150  : _Base(__str, __pos, __n) { }
151 
152  // _GLIBCXX_RESOLVE_LIB_DEFECTS
153  // 396. what are characters zero and one.
154  template<class _CharT, class _Traits, class _Alloc>
155  bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
156  typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
157  __pos,
158  typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
159  __n,
160  _CharT __zero, _CharT __one = _CharT('1'))
161  : _Base(__str, __pos, __n, __zero, __one) { }
162 
163  bitset(const _Base& __x) : _Base(__x) { }
164 
165 #if __cplusplus >= 201103L
166  template<typename _CharT>
167  explicit
168  bitset(const _CharT* __str,
169  typename std::basic_string<_CharT>::size_type __n
170  = std::basic_string<_CharT>::npos,
171  _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'))
172  : _Base(__str, __n, __zero, __one) { }
173 #endif
174 
175  // 23.3.5.2 bitset operations:
176  bitset<_Nb>&
177  operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
178  {
179  _M_base() &= __rhs;
180  return *this;
181  }
182 
183  bitset<_Nb>&
184  operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
185  {
186  _M_base() |= __rhs;
187  return *this;
188  }
189 
190  bitset<_Nb>&
191  operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
192  {
193  _M_base() ^= __rhs;
194  return *this;
195  }
196 
197  bitset<_Nb>&
198  operator<<=(size_t __pos) _GLIBCXX_NOEXCEPT
199  {
200  _M_base() <<= __pos;
201  return *this;
202  }
203 
204  bitset<_Nb>&
205  operator>>=(size_t __pos) _GLIBCXX_NOEXCEPT
206  {
207  _M_base() >>= __pos;
208  return *this;
209  }
210 
211  bitset<_Nb>&
212  set() _GLIBCXX_NOEXCEPT
213  {
214  _Base::set();
215  return *this;
216  }
217 
218  // _GLIBCXX_RESOLVE_LIB_DEFECTS
219  // 186. bitset::set() second parameter should be bool
220  bitset<_Nb>&
221  set(size_t __pos, bool __val = true)
222  {
223  _Base::set(__pos, __val);
224  return *this;
225  }
226 
227  bitset<_Nb>&
228  reset() _GLIBCXX_NOEXCEPT
229  {
230  _Base::reset();
231  return *this;
232  }
233 
234  bitset<_Nb>&
235  reset(size_t __pos)
236  {
237  _Base::reset(__pos);
238  return *this;
239  }
240 
241  bitset<_Nb>
242  operator~() const _GLIBCXX_NOEXCEPT
243  { return bitset(~_M_base()); }
244 
245  bitset<_Nb>&
246  flip() _GLIBCXX_NOEXCEPT
247  {
248  _Base::flip();
249  return *this;
250  }
251 
252  bitset<_Nb>&
253  flip(size_t __pos)
254  {
255  _Base::flip(__pos);
256  return *this;
257  }
258 
259  // element access:
260  // _GLIBCXX_RESOLVE_LIB_DEFECTS
261  // 11. Bitset minor problems
262  reference
263  operator[](size_t __pos)
264  {
265  __glibcxx_check_subscript(__pos);
266 #if __cplusplus >= 201103L
267  return _M_base()[__pos];
268 #else
269  return reference(_M_base()[__pos], this);
270 #endif
271  }
272 
273  // _GLIBCXX_RESOLVE_LIB_DEFECTS
274  // 11. Bitset minor problems
275  _GLIBCXX_CONSTEXPR bool
276  operator[](size_t __pos) const
277  {
278 #if __cplusplus < 201103L
279  // TODO: Check in debug-mode too.
280  __glibcxx_check_subscript(__pos);
281 #endif
282  return _Base::operator[](__pos);
283  }
284 
285  using _Base::to_ulong;
286 #if __cplusplus >= 201103L
287  using _Base::to_ullong;
288 #endif
289 
290  template <typename _CharT, typename _Traits, typename _Alloc>
291  std::basic_string<_CharT, _Traits, _Alloc>
292  to_string() const
293  { return _M_base().template to_string<_CharT, _Traits, _Alloc>(); }
294 
295  // _GLIBCXX_RESOLVE_LIB_DEFECTS
296  // 396. what are characters zero and one.
297  template<class _CharT, class _Traits, class _Alloc>
298  std::basic_string<_CharT, _Traits, _Alloc>
299  to_string(_CharT __zero, _CharT __one = _CharT('1')) const
300  {
301  return _M_base().template
302  to_string<_CharT, _Traits, _Alloc>(__zero, __one);
303  }
304 
305  // _GLIBCXX_RESOLVE_LIB_DEFECTS
306  // 434. bitset::to_string() hard to use.
307  template<typename _CharT, typename _Traits>
308  std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
309  to_string() const
310  { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); }
311 
312  // _GLIBCXX_RESOLVE_LIB_DEFECTS
313  // 853. to_string needs updating with zero and one.
314  template<class _CharT, class _Traits>
315  std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
316  to_string(_CharT __zero, _CharT __one = _CharT('1')) const
317  { return to_string<_CharT, _Traits,
318  std::allocator<_CharT> >(__zero, __one); }
319 
320  template<typename _CharT>
321  std::basic_string<_CharT, std::char_traits<_CharT>,
322  std::allocator<_CharT> >
323  to_string() const
324  {
325  return to_string<_CharT, std::char_traits<_CharT>,
326  std::allocator<_CharT> >();
327  }
328 
329  template<class _CharT>
330  std::basic_string<_CharT, std::char_traits<_CharT>,
331  std::allocator<_CharT> >
332  to_string(_CharT __zero, _CharT __one = _CharT('1')) const
333  {
334  return to_string<_CharT, std::char_traits<_CharT>,
335  std::allocator<_CharT> >(__zero, __one);
336  }
337 
338  std::basic_string<char, std::char_traits<char>, std::allocator<char> >
339  to_string() const
340  {
341  return to_string<char,std::char_traits<char>,std::allocator<char> >();
342  }
343 
344  std::basic_string<char, std::char_traits<char>, std::allocator<char> >
345  to_string(char __zero, char __one = '1') const
346  {
347  return to_string<char, std::char_traits<char>,
348  std::allocator<char> >(__zero, __one);
349  }
350 
351  using _Base::count;
352  using _Base::size;
353 
354  bool
355  operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
356  { return _M_base() == __rhs._M_base(); }
357 
358 #if __cpp_impl_three_way_comparison < 201907L
359  bool
360  operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
361  { return _M_base() != __rhs._M_base(); }
362 #endif
363 
364  using _Base::test;
365  using _Base::all;
366  using _Base::any;
367  using _Base::none;
368 
369  bitset<_Nb>
370  operator<<(size_t __pos) const _GLIBCXX_NOEXCEPT
371  { return bitset<_Nb>(_M_base() << __pos); }
372 
373  bitset<_Nb>
374  operator>>(size_t __pos) const _GLIBCXX_NOEXCEPT
375  { return bitset<_Nb>(_M_base() >> __pos); }
376 
377  _Base&
378  _M_base() _GLIBCXX_NOEXCEPT
379  { return *this; }
380 
381  const _Base&
382  _M_base() const _GLIBCXX_NOEXCEPT
383  { return *this; }
384  };
385 
386  template<size_t _Nb>
387  bitset<_Nb>
388  operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
389  { return bitset<_Nb>(__x) &= __y; }
390 
391  template<size_t _Nb>
392  bitset<_Nb>
393  operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
394  { return bitset<_Nb>(__x) |= __y; }
395 
396  template<size_t _Nb>
397  bitset<_Nb>
398  operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
399  { return bitset<_Nb>(__x) ^= __y; }
400 
401  template<typename _CharT, typename _Traits, size_t _Nb>
402  std::basic_istream<_CharT, _Traits>&
403  operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x)
404  { return __is >> __x._M_base(); }
405 
406  template<typename _CharT, typename _Traits, size_t _Nb>
407  std::basic_ostream<_CharT, _Traits>&
408  operator<<(std::basic_ostream<_CharT, _Traits>& __os,
409  const bitset<_Nb>& __x)
410  { return __os << __x._M_base(); }
411 
412 } // namespace __debug
413 
414 #if __cplusplus >= 201103L
415  // DR 1182.
416  /// std::hash specialization for bitset.
417  template<size_t _Nb>
418  struct hash<__debug::bitset<_Nb>>
419  : public __hash_base<size_t, __debug::bitset<_Nb>>
420  {
421  size_t
422  operator()(const __debug::bitset<_Nb>& __b) const noexcept
423  { return std::hash<_GLIBCXX_STD_C::bitset<_Nb>>()(__b._M_base()); }
424  };
425 #endif
426 
427 } // namespace std
428 
429 #endif