diff --git a/CMakeLists.txt b/CMakeLists.txt index 8de0ed4..64699e5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,6 @@ # Generated by `boostdep --cmake dynamic_bitset` # Copyright 2020 Peter Dimov +# Copyright 2025 Gennaro Prota # Distributed under the Boost Software License, Version 1.0. # https://www.boost.org/LICENSE_1_0.txt @@ -30,3 +31,21 @@ if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt") endif() +if (DYNAMIC_BITSET_MRDOCS_BUILD) + set(INCLUDE_DIR "${CMAKE_SOURCE_DIR}/include") + + # Create a temporary source file that includes boost/dynamic_bitset.hpp. + set(TEMP_CPP_FILE "${CMAKE_CURRENT_BINARY_DIR}/dynamic_bitset_for_mrdocs.cpp") + file(WRITE ${TEMP_CPP_FILE} "// This file is generated automatically by CMake\n\n") + file(APPEND ${TEMP_CPP_FILE} "#include \"boost/dynamic_bitset.hpp\"\n") + + # Create a custom target for MrDocs. + add_library(dynamic_bitset_mrdocs_target ${TEMP_CPP_FILE}) + + # Set any other target properties here. + target_include_directories(dynamic_bitset_mrdocs_target PRIVATE ${INCLUDE_DIR}) + target_link_libraries(dynamic_bitset_mrdocs_target PRIVATE boost_dynamic_bitset) + + # Don't create any other targets. + return() +endif() diff --git a/doc/antora.yml b/doc/antora.yml new file mode 100644 index 0000000..279f004 --- /dev/null +++ b/doc/antora.yml @@ -0,0 +1,21 @@ +# ============================================================================ +# Copyright 2025 Gennaro Prota. +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# ============================================================================ + +name: dynamic_bitset +version: ~ +title: Boost.DynamicBitset +start_page: index.adoc +asciidoc: + attributes: + source-language: asciidoc@ + table-caption: false +nav: + - modules/ROOT/nav.adoc +ext: + cpp-reference: + config: doc/mrdocs.yml diff --git a/doc/build_docs.sh b/doc/build_docs.sh new file mode 100755 index 0000000..0f2c837 --- /dev/null +++ b/doc/build_docs.sh @@ -0,0 +1,28 @@ +#! /bin/sh -- +# ============================================================================ +# Copyright 2023 Alan de Freitas. +# Copyright 2025 Gennaro Prota. +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# ============================================================================ + +set -eu + +if [ $# -eq 0 ] +then + echo "No playbook supplied, using default playbook." + PLAYBOOK="local-playbook.yml" +else + PLAYBOOK=$1 +fi + +echo "Installing npm dependencies..." +npm ci + +echo "Building docs in custom dir..." +PATH="$(pwd)/node_modules/.bin:${PATH}" +export PATH +npx antora --clean --fetch "$PLAYBOOK" --stacktrace --log-level all +echo "Done" diff --git a/doc/local-playbook.yml b/doc/local-playbook.yml new file mode 100644 index 0000000..694f335 --- /dev/null +++ b/doc/local-playbook.yml @@ -0,0 +1,55 @@ +# ============================================================================ +# Copyright 2023 Alan de Freitas. +# Copyright 2025 Gennaro Prota. +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# ============================================================================ +# +# An antora playbook used for local development. +# The playbook includes Boost.DynamicBitset as its only component. +# ---------------------------------------------------------------------------- + +site: + title: Boost.DynamicBitset + url: https://antora.cppalliance.org/develop/lib/doc + start_page: dynamic_bitset::index.adoc + robots: allow + keys: + repo_url: 'https://github.com/boostorg/dynamic_bitset' + +content: + sources: + - url: .. + start_path: doc + edit_url: 'https://github.com/boostorg/dynamic_bitset/edit/{refname}/{path}' + +ui: + bundle: + url: https://github.com/boostorg/website-v2-docs/releases/download/ui-master/ui-bundle.zip + snapshot: true + +antora: + extensions: + - require: '@antora/lunr-extension' # https://gitlab.com/antora/antora-lunr-extension + index_latest_only: true + - require: '@cppalliance/antora-cpp-tagfiles-extension' + cpp-tagfiles: + using-namespaces: + - 'boost::' + - require: '@cppalliance/antora-cpp-reference-extension' + dependencies: + - name: 'boost' + repo: 'https://github.com/boostorg/boost.git' + tag: 'develop' + variable: 'BOOST_SRC_DIR' + system-env: 'BOOST_SRC_DIR' + +asciidoc: + attributes: + # Enable pagination + page-pagination: '' + extensions: + - '@cppalliance/asciidoctor-boost-links' + - '@asciidoctor/tabs' diff --git a/doc/modules/ROOT/nav.adoc b/doc/modules/ROOT/nav.adoc new file mode 100644 index 0000000..6fd0258 --- /dev/null +++ b/doc/modules/ROOT/nav.adoc @@ -0,0 +1,10 @@ +// =========================================================================== +// Copyright 2025 Gennaro Prota. +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// =========================================================================== + +* xref:index.adoc[] +* xref:reference.adoc[Reference] diff --git a/doc/modules/ROOT/pages/index.adoc b/doc/modules/ROOT/pages/index.adoc new file mode 100644 index 0000000..a9e5503 --- /dev/null +++ b/doc/modules/ROOT/pages/index.adoc @@ -0,0 +1,79 @@ +// =========================================================================== +// Copyright 2001 Jeremy Siek +// Copyright 2003-2004, 2008, 2025 Gennaro Prota +// Copyright 2014 Ahmed Charles +// Copyright 2014 Riccardo Marcangelo +// Copyright 2018 Evgeny Shulgin +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// =========================================================================== + += Boost.DynamicBitset + +Boost.DynamicBitset is a portable library that provides a set of bits. + +The set (`boost::dynamic_bitset`) provides access to the value of individual +bits via `operator[]` and provides all of the bitwise operators that one can +apply to builtin integers, such as `operator&` and `operator<<`. The number of +bits can change at runtime. + +`dynamic_bitset` is nearly identical to `std::bitset`. The difference is that +the size of a `dynamic_bitset` (the number of bits) can change at runtime, +whereas the size of a `std::bitset` is specified at compile-time through an +integer template parameter. + +The main problem that `dynamic_bitset` is designed to solve is that of +representing a subset of a finite set. Each bit represents whether an element of +the finite set is in the subset or not. As such the bitwise operations of +`dynamic_bitset`, such as `operator&` and `operator|`, correspond to set +operations, such as intersection and union. + +== Definitions +Each bit represents either the Boolean value `true` or `false` (1 or 0). To set +a bit is to assign it 1. To clear or reset a bit is to assign it 0. To flip a +bit is to change the value to 1 if it was 0 and to 0 if it was 1. Each bit has a +non-negative position. A bitset `x` contains `x.size()` bits, with each bit +assigned a unique position in the range `[0, x.size())`. The bit at position 0 +is called the least significant bit and the bit at position `size() - 1` is the +most significant bit. When converting an instance of `dynamic_bitset` to or from +an unsigned long `n`, the bit at position `i` of the bitset has the same value +as `(n >> i) & 1`. + +== Rationale +`dynamic_bitset` is not a Container +and does not provide iterators for the following reason: + +A container with a proxy reference type can not fulfill the container +requirements as specified in the C++ standard (unless one resorts to strange +iterator semantics). `std::vector` has a proxy reference type and does not +fulfill the container requirements and as a result has caused many problems. One +common problem is when people try to use iterators from `std::vector` with +a standard algorithm such as `std::search()`. The `std::search()` requirements +say that the iterator must be a LegacyForwardIterator, but +`std::vector::iterator` does not meet this requirement because of the +proxy reference. Depending on the implementation, they may or not be a compile +error or even a run-time error due to this misuse. For further discussion of the +problem see "Effective STL" by Scott Meyers. So `dynamic_bitset` tries to avoid +these problems by not pretending to be a container. + +Some people prefer the name "toggle" to "flip". The name "flip" was chosen +because that is the name used in `std::bitset`. In fact, most of the function +names for `dynamic_bitset` were chosen for this reason. + +`dynamic_bitset` does not throw exceptions when a precondition is violated (as +is done in `std::bitset`). Instead `BOOST_ASSERT()` is used. See the guidelines +for Error and Exception Handling for the explanation. Note that, consistently +with this, the documentation of the member functions doesn't use the term +"precondition" for conditions that cause an exception to be emitted (the C++ +standard uses the term "requires" in such cases). + +== Acknowledgments + +We would like to thank the Boost community for putting in the time to review and +accept this library. This library is much better than it ever would have been +due to all the suggestions from Boost members. We especially thank Matt Marcus +for taking on the task of review manager. Also, a special thanks goes to James +Kanze for his invaluable help with the internationalization issues. diff --git a/doc/mrdocs.yml b/doc/mrdocs.yml new file mode 100644 index 0000000..ce7bc3b --- /dev/null +++ b/doc/mrdocs.yml @@ -0,0 +1,25 @@ +# ============================================================================ +# Copyright 2025 Gennaro Prota. +# +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# ============================================================================ + +verbose: true +source-root: .. +cmake: '-DDYNAMIC_BITSET_MRDOCS_BUILD=ON' +input: + - ../include +exclude-symbols: + - 'boost::detail' + - 'boost::detail::**' + - 'boost::to_string_helper' + - 'std' + - 'std::**' + # Why does MrDocs pick up ::size_t? + - 'size_t' +file-patterns: + - '*.hpp' +multipage: false +generator: adoc diff --git a/doc/readme b/doc/readme index 73f7575..1035831 100644 --- a/doc/readme +++ b/doc/readme @@ -1 +1 @@ -The documentation for the dynamic_bitset library is the top-level index.html file. \ No newline at end of file +To build the documentation, run build_docs.sh. diff --git a/dynamic_bitset.html b/dynamic_bitset.html deleted file mode 100644 index 79d40c2..0000000 --- a/dynamic_bitset.html +++ /dev/null @@ -1,1775 +0,0 @@ - - - - - - - -dynamic_bitset<Block, Allocator> - - - - -
-
-
-
-
-
- - -

dynamic_bitset<Block, Allocator>

-

Contents

- -
-
Description
-
Synopsis
-
Definitions
-
Examples
-
Rationale
-
Header files
-
Template parameters
-
Concepts modeled
- -
Type requirements
-
Public base classes
-
Nested type names
-
Public data members
-
Constructors
-
Destructor
-
Member functions
-
Non-member functions
-
Exception guarantees
- -
Changes from previous version(s)
-
See also
-
Acknowledgements
-
-

Description

-

The dynamic_bitset template represents a set of -bits. It provides access to the value of individual bits via -operator[] and provides all of the bitwise operators -that one can apply to builtin integers, such as -operator& and operator<<. The number -of bits in the set can change at runtime.

- -

The dynamic_bitset class is nearly identical to the -std::bitset -class. The difference is that the size of a -dynamic_bitset (the number of bits) can change at runtime, -whereas the size of a std::bitset is specified at compile-time -through an integer template parameter.

- -

The main problem that dynamic_bitset is designed to -solve is that of representing a subset of a finite set. Each bit -represents whether an element of the finite set is in the subset -or not. As such the bitwise operations of -dynamic_bitset, such as operator& and -operator|, correspond to set operations, such as -intersection and union.

-

Synopsis

-
-namespace boost {
-
-template <typename Block, typename Allocator>
-class dynamic_bitset
-{
-public:
-    typedef Block block_type;
-    typedef Allocator allocator_type;
-    typedef implementation-defined size_type;
-
-    static const int bits_per_block = implementation-defined;
-    static const size_type npos = implementation-defined;
-
-    class reference
-    {
-        void operator&(); // not defined
-
-    public:
-        // An automatically generated copy constructor.
-
-        reference& operator=(bool value);
-        reference& operator=(const reference& rhs);
-
-        reference& operator|=(bool value);
-        reference& operator&=(bool value);
-        reference& operator^=(bool value);
-        reference& operator-=(bool value);
-
-        bool operator~() const;
-        operator bool() const;
-        reference& flip();
-    };
-
-    typedef bool const_reference;
-
-    dynamic_bitset();
-
-    explicit dynamic_bitset(const Allocator& alloc);
-
-    explicit dynamic_bitset(size_type num_bits, unsigned long value = 0,
-                            const Allocator& alloc = Allocator());
-
-    template <typename CharT, typename Traits, typename Alloc>
-    explicit dynamic_bitset(const std::basic_string<CharT, Traits, Alloc>& s,
-        typename std::basic_string<CharT, Traits, Alloc>::size_type pos = 0,
-        typename std::basic_string<CharT, Traits, Alloc>::size_type n = std::basic_string<CharT, Traits, Alloc>::npos,
-        const Allocator& alloc = Allocator());
-
-    template <typename BlockInputIterator>
-    dynamic_bitset(BlockInputIterator first, BlockInputIterator last,
-                   const Allocator& alloc = Allocator());
-
-    dynamic_bitset(const dynamic_bitset& b);
-
-    dynamic_bitset(dynamic_bitset&& b);
-
-    void swap(dynamic_bitset& b) noexcept;
-
-    dynamic_bitset& operator=(const dynamic_bitset& b);
-
-    dynamic_bitset& operator=(dynamic_bitset&& b);
-
-    allocator_type get_allocator() const;
-
-    void resize(size_type num_bits, bool value = false);
-    void clear();
-    void pop_back();
-    void push_back(bool bit);
-    void append(Block block);
-
-    template <typename BlockInputIterator>
-    void append(BlockInputIterator first, BlockInputIterator last);
-
-    dynamic_bitset& operator&=(const dynamic_bitset& b);
-    dynamic_bitset& operator|=(const dynamic_bitset& b);
-    dynamic_bitset& operator^=(const dynamic_bitset& b);
-    dynamic_bitset& operator-=(const dynamic_bitset& b);
-    dynamic_bitset& operator<<=(size_type n);
-    dynamic_bitset& operator>>=(size_type n);
-    dynamic_bitset operator<<(size_type n) const;
-    dynamic_bitset operator>>(size_type n) const;
-
-    dynamic_bitset& set(size_type n, size_type len, bool val);
-    dynamic_bitset& set(size_type n, bool val = true);
-    dynamic_bitset& set();
-    dynamic_bitset& reset(size_type n, size_type len);
-    dynamic_bitset& reset(size_type n);
-    dynamic_bitset& reset();
-    dynamic_bitset& flip(size_type n, size_type len);
-    dynamic_bitset& flip(size_type n);
-    dynamic_bitset& flip();
-    reference at(size_type n);
-    bool at(size_type n) const;
-    bool test(size_type n) const;
-    bool test_set(size_type n, bool val = true);
-    bool all() const;
-    bool any() const;
-    bool none() const;
-    dynamic_bitset operator~() const;
-    size_type count() const noexcept;
-
-    reference operator[](size_type pos);
-    bool operator[](size_type pos) const;
-
-    unsigned long to_ulong() const;
-
-    size_type size() const noexcept;
-    size_type num_blocks() const noexcept;
-    size_type max_size() const noexcept;
-    bool empty() const noexcept;
-    size_type capacity() const noexcept;
-    void reserve(size_type num_bits);
-    void shrink_to_fit();
-
-    bool is_subset_of(const dynamic_bitset& a) const;
-    bool is_proper_subset_of(const dynamic_bitset& a) const;
-    bool intersects(const dynamic_bitset& a) const;
-
-    size_type find_first() const;
-    size_type find_first(size_type pos) const;
-    size_type find_next(size_type pos) const;
-
-};
-
-
-template <typename B, typename A>
-bool operator==(const dynamic_bitset<B, A>& a, const dynamic_bitset<B, A>& b);
-
-template <typename Block, typename Allocator>
-bool operator!=(const dynamic_bitset<Block, Allocator>& a, const dynamic_bitset<Block, Allocator>& b);
-
-template <typename B, typename A>
-bool operator<(const dynamic_bitset<B, A>& a, const dynamic_bitset<B, A>& b);
-
-template <typename Block, typename Allocator>
-bool operator<=(const dynamic_bitset<Block, Allocator>& a, const dynamic_bitset<Block, Allocator>& b);
-
-template <typename Block, typename Allocator>
-bool operator>(const dynamic_bitset<Block, Allocator>& a, const dynamic_bitset<Block, Allocator>& b);
-
-template <typename Block, typename Allocator>
-bool operator>=(const dynamic_bitset<Block, Allocator>& a, const dynamic_bitset<Block, Allocator>& b);
-
-template <typename Block, typename Allocator>
-dynamic_bitset<Block, Allocator>
-operator&(const dynamic_bitset<Block, Allocator>& b1, const dynamic_bitset<Block, Allocator>& b2);
-
-template <typename Block, typename Allocator>
-dynamic_bitset<Block, Allocator>
-operator|(const dynamic_bitset<Block, Allocator>& b1, const dynamic_bitset<Block, Allocator>& b2);
-
-template <typename Block, typename Allocator>
-dynamic_bitset<Block, Allocator>
-operator^(const dynamic_bitset<Block, Allocator>& b1, const dynamic_bitset<Block, Allocator>& b2);
-
-template <typename Block, typename Allocator>
-dynamic_bitset<Block, Allocator>
-operator-(const dynamic_bitset<Block, Allocator>& b1, const dynamic_bitset<Block, Allocator>& b2);
-
-template <typename Block, typename Allocator, typename CharT, typename Alloc>
-void to_string(const dynamic_bitset<Block, Allocator>& b,
-          std::basic_string<CharT, Alloc>& s);
-
-template <typename Block, typename Allocator, typename BlockOutputIterator>
-void to_block_range(const dynamic_bitset<Block, Allocator>& b,
-                    BlockOutputIterator result);
-
-template <typename CharT, typename Traits, typename Block, typename Allocator>
-std::basic_ostream<CharT, Traits>&
-operator<<(std::basic_ostream<CharT, Traits>& os, const dynamic_bitset<Block, Allocator>& b);
-
-template <typename CharT, typename Traits, typename Block, typename Allocator>
-std::basic_istream<CharT, Traits>&
-operator>>(std::basic_istream<CharT, Traits>& is, dynamic_bitset<Block, Allocator>& b);
-
-} // namespace boost
-
- -

Definitions

- -

Each bit represents either the Boolean value true or false (1 -or 0). To set a bit is to assign it 1. To clear or -reset a bit is to assign it 0. To flip a bit is to -change the value to 1 if it was 0 and to 0 if it was 1. Each bit -has a non-negative position. A bitset x contains -x.size() bits, with each bit assigned a unique position -in the range [0,x.size()). The bit at position 0 is -called the least significant bit and the bit at position -size() - 1 is the most significant bit. When -converting an instance of dynamic_bitset to or from an -unsigned long n, the bit at position i of the -bitset has the same value as (n >> i) & 1.

- -

Examples

- -

-Example 1 (setting -and reading some bits) -

-

-Example 2 (creating -some bitsets from integers) -

- -

-Example 3 (performing -input/output and some bitwise operations). -

- - -

Rationale

-

-dynamic_bitset is not a Container and -does not provide iterators for the following reason: -

- -
    -
  • A container with a proxy reference type can not -fulfill the container requirements as specified in the C++ -standard (unless one resorts to strange iterator semantics). -std::vector<bool> has a proxy reference -type and does not fulfill the container requirements and as a -result has caused many problems. One common problem is when -people try to use iterators from std::vector<bool> -with a Standard algorithm such as std::search. The -std::search requirements say that the iterator must be a -LegacyForwardIterator, -but the std::vector<bool>::iterator -does not meet this requirement because of the proxy reference. -Depending on the implementation, they may or not be a compile -error or even a run-time error due to this misuse. For further -discussion of the problem see Effective STL by Scott -Meyers). So dynamic_bitset tries to avoid these problems -by not pretending to be a container.
  • -
- -

Some people prefer the name "toggle" to "flip". The name -"flip" was chosen because that is the name used in std::bitset. -In fact, most of the function names for dynamic_bitset -were chosen for this reason.

- -

dynamic_bitset does not throw exceptions when a -precondition is violated (as is done in std::bitset). -Instead BOOST_ASSERT is used. See the guidelines for Error and Exception Handling -for the explanation. Note that, consistently with this, the documentation of the -various functions doesn't use the term "precondition" for conditions that cause -an exception to be emitted (the C++ standard uses the term "requires" in such -cases).

- -

Header files

- -

The class dynamic_bitset is defined in the header boost/dynamic_bitset.hpp. -Also, there is a forward declaration for dynamic_bitset -in the header boost/dynamic_bitset_fwd.hpp.

- -

Template parameters

- - - - - - - - - - - - - - - - - - -
ParameterDescriptionDefault
BlockThe integer type in which the bits are stored.unsigned long
AllocatorThe allocator type used for all internal memory management.std::allocator<Block>
-

Concepts modeled

-CopyAssignable, DefaultConstructible, EqualityComparable, LessThanComparable. - -

Type requirements

- -Block is an unsigned integer type. Allocator -satisfies the Standard requirements for an allocator. - -

Public base classes

- -None. -

Nested type names

-
- -
-dynamic_bitset::reference
-
- -

A proxy class that acts as a reference to a single bit. It -contains an assignment operator, a conversion to bool, -an operator~, and a member function flip. It -exists only as a helper class for dynamic_bitset's -operator[]. The following table describes the valid -operations on the reference type. Assume that b -is an instance of dynamic_bitset, i, j are of -size_type and in the range [0,b.size()). Also, -note that when we write b[i] we mean an object of type -reference that was initialized from b[i]. The -variable x is a bool.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ExpressionSemantics
x = b[i]Assign the ith bit of b to x.
(bool)b[i]Return the ith bit of b.
b[i] = xSet the ith bit of b to the value of x and -return b[i].
b[i] |= xOr the ith bit of b with the value of x and -return b[i].
b[i] &= xAnd the ith bit of b with the value of x -and return b[i].
b[i] ^= xExclusive-Or the ith bit of b with the value of -x and return b[i].
b[i] -= xIf x==true, clear the ith bit of b. Returns -b[i].
b[i] = b[j]Set the ith bit of b to the value of the jth bit of -b and return b[i].
b[i] |= b[j]Or the ith bit of b with the jth bit of b -and return b[i].
b[i] &= b[j]And the ith bit of b with the jth bit of b and return b[i].
b[i] ^= b[j]Exclusive-Or the ith bit of b with the jth bit of b and return b[i].
b[i] -= b[j]If the jth bit of b is set, clear the ith bit of b. Returns b[i].
x = ~b[i]Assign the opposite of the ith bit of b to x.
(bool)~b[i]Return the opposite of the ith bit of b.
b[i].flip()Flip the ith bit of b and return b[i].
-
-
-dynamic_bitset::const_reference
-
-The type bool. - -
-dynamic_bitset::size_type
-
-The unsigned integer type for representing the size of the bit set. - -
-dynamic_bitset::block_type
-
-The same type as Block. - -
-dynamic_bitset::allocator_type;
-
-The same type as Allocator. - - -
-

Public data members

- -
-dynamic_bitset::bits_per_block
-
-The number of bits the type Block uses to represent values, -excluding any padding bits. Numerically equal -to std::numeric_limits<Block>::digits. - -
-dynamic_bitset::npos
-
-The maximum value of size_type. - -
-

Constructors

- -
-
-dynamic_bitset()
-
- -Effects: Constructs a bitset of size zero. The allocator -for this bitset is a default-constructed object of type -Allocator.
- Postconditions: this->size() == 0.
- Throws: Nothing unless the default constructor of -Allocator throws an exception.
- (Required by DefaultConstructible.) - -
-
-dynamic_bitset(const Allocator& alloc)
-
- -Effects: Constructs a bitset of size zero. A copy of the -alloc object will be used in subsequent bitset -operations such as resize to allocate memory.
- Postconditions: this->size() == 0.
- Throws: nothing. - -
-
-dynamic_bitset(size_type num_bits,
-               unsigned long value = 0,
-               const Allocator& alloc = Allocator())
-
- -Effects: Constructs a bitset from an integer. The first -M bits are initialized to the corresponding bits in -value and all other bits, if any, to zero (where M = -min(num_bits, std::numeric_limits<unsigned long>::digits)). A copy of -the alloc object will be used in subsequent bitset -operations such as resize to allocate memory. Note that, e.g., the -following -

- -dynamic_bitset b<>( 16, 7 ); -

-will match the constructor from an iterator range (not this -one), but the underlying implementation will still "do the right thing" and -construct a bitset of 16 bits, from the value 7. -
-Postconditions: - -
    -
  • this->size() == num_bits
  • - -
  • For all i in the range [0,M), -(*this)[i] == (value >> i) & 1.
  • - -
  • For all i in the range [M,num_bits), -(*this)[i] == false.
  • -
- -Throws: An allocation error if memory is exhausted -(std::bad_alloc if -Allocator=std::allocator).
- - -
-
-dynamic_bitset(const dynamic_bitset& x)
-
- -Effects: Constructs a bitset that is a copy of the bitset -x. The allocator for this bitset is a copy of the -allocator in x.
- Postconditions: For all i in the range -[0,x.size()), (*this)[i] == x[i].
- Throws: An allocation error if memory is exhausted -(std::bad_alloc if -Allocator=std::allocator).
- (Required by CopyConstructible.) - -
-
-dynamic_bitset(dynamic_bitset&& x)
-
- -Effects: Constructs a bitset that is the same as the bitset -x, while using the resources from x. The allocator -for this bitset is moved from the allocator in x.
- Postconditions: For all i in the range -[0,x.size()), (*this)[i] == x[i].
- Throws: An allocation error if memory is exhausted -(std::bad_alloc if -Allocator=std::allocator). - -
-
-template <typename BlockInputIterator>
-explicit
-dynamic_bitset(BlockInputIterator first, BlockInputIterator last,
-               const Allocator& alloc = Allocator());
-
- -Effects: -
    -
  • -If this constructor is called with a type BlockInputIterator which -is actually an integral type, the library behaves as if the constructor -from unsigned long were called, with arguments -static_cast<size_type>(first), last and alloc, in that order. -

    -Example: -
    -// b is constructed as if by calling the constructor
    -//
    -//   dynamic_bitset(size_type num_bits,
    -//                  unsigned long value = 0,
    -//                  const Allocator& alloc = Allocator())
    -//
    -// with arguments
    -//
    -//   static_cast<dynamic_bitset<unsigned short>::size_type>(8),
    -//   7,
    -//   Allocator()
    -//
    -dynamic_bitset<unsigned short> b(8, 7);
    -

    -Note:
    -At the time of writing (October 2008) this is aligned with the -proposed resolution for library - issue 438. That is a post C++03 -change, and is currently in the working paper for -C++0x. Informally speaking, the critical changes with -respect to C++03 are the drop of a static_cast -on the second argument, and more leeway as to when the -templated constructor should have the same effect as the (size, -value) one: only when InputIterator is an integral -type, in C++03; when it is either an integral type or -any other type that the implementation might detect as -impossible to be an input iterator, with the proposed -resolution. For the purposes of dynamic_bitset we limit -ourselves to the first of these two changes.

    -
  • -
  • -Otherwise (i.e. if the template argument is not an -integral type), constructs—under the condition in the -requires clause—a bitset based on a range of -blocks. Let *first be block number 0, *++first -block number 1, etc. Block number b is used to -initialize the bits of the dynamic_bitset in the position range -[b*bits_per_block, (b+1)*bits_per_block). For each -block number b with value bval, the bit -(bval >> i) & 1 corresponds to the bit at -position (b * bits_per_block + i) in the bitset (where -i goes through the range [0, bits_per_block)). -
  • -
-
-Requires: BlockInputIterator must be either an -integral type or a model of LegacyInputIterator -whose value_type is the same type as -Block.
Throws: An allocation error if -memory is exhausted (std::bad_alloc if -Allocator=std::allocator).
- -
-
-template<typename Char, typename Traits, typename Alloc>
-explicit
-dynamic_bitset(const std::basic_string<Char,Traits,Alloc>& s,
-               typename std::basic_string<CharT, Traits, Alloc>::size_type pos = 0,
-               typename std::basic_string<CharT, Traits, Alloc>::size_type n = std::basic_string<Char,Traits,Alloc>::npos,
-               const Allocator& alloc = Allocator())
-
- -Precondition: pos <= s.size() and the -characters used to initialize the bits must be 0 or -1.
- Effects: Constructs a bitset from a string of 0's and -1's. The first M bits are initialized to the -corresponding characters in s, where M = -min(s.size() - pos, n). Note that the highest -character position in s, not the lowest, corresponds to -the least significant bit. That is, character position pos + -M - 1 - i corresponds to bit i. So, for example, -dynamic_bitset(string("1101")) is the same as -dynamic_bitset(13ul).
- Throws: an allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-

Destructor

- -
-
-~dynamic_bitset()
-
- -Effects: Releases the memory associated with this bitset -and destroys the bitset object itself.
- Throws: nothing. - -
-

Member functions

- -
-
-void swap(dynamic_bitset& b) noexcept;
-
- -Effects: The contents of this bitset and bitset b -are exchanged.
-Postconditions: This bitset is equal to the original -b, and b is equal to the previous version of -this bitset.
-Throws: nothing. - -
-
-dynamic_bitset& operator=(const dynamic_bitset& x)
-
- -Effects: This bitset becomes a copy of the bitset -x.
- Postconditions: For all i in the range -[0,x.size()), (*this)[i] == x[i].
- Returns: *this.
- Throws: nothing.
-(Required by CopyAssignable.) - -
-
-dynamic_bitset& operator=(dynamic_bitset&& x)
-
- -Effects: This bitset becomes the same as the bitset -x, while using the resources from x.
- Postconditions: For all i in the range -[0,x.size()), (*this)[i] == x[i].
- Returns: *this.
- Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-allocator_type get_allocator() const;
-
- Returns: A copy of the allocator object used to construct *this. - -
-
-void resize(size_type num_bits, bool value = false);
-
- -Effects: Changes the number of bits of the bitset to -num_bits. If num_bits > size() then the bits -in the range [0,size()) remain the same, and the bits in -[size(),num_bits) are all set to value. If -num_bits < size() then the bits in the range -[0,num_bits) stay the same (and the remaining bits are -discarded).
- Postconditions: this->size() == num_bits.
- Throws: An allocation error if memory is exhausted -(std::bad_alloc if -Allocator=std::allocator).
- - -
-
-void clear()
-
- -Effects: The size of the bitset becomes zero.
- Throws: nothing. - -
-
-void pop_back();
-
- -Precondition: !this->empty().
-Effects: Decreases the size of the bitset by one.
- Throws: nothing. - -
-
-void push_back(bool value);
-
- -Effects: Increases the size of the bitset by one, and sets -the value of the new most-significant bit to value.
- Throws: An allocation error if memory is exhausted -(std::bad_alloc if -Allocator=std::allocator).
- - -
-
-void append(Block value);
-
- -Effects: Appends the bits in value to the bitset -(appends to the most-significant end). This increases the size of -the bitset by bits_per_block. Let s be the old -size of the bitset, then for i in the range -[0,bits_per_block), the bit at position (s + i) -is set to ((value >> i) & 1).
- Throws: An allocation error if memory is exhausted -(std::bad_alloc if -Allocator=std::allocator).
- - -
-
-template <typename BlockInputIterator>
-void append(BlockInputIterator first, BlockInputIterator last);
-
- -Effects: This function provides the same end result as the -following code, but is typically more efficient. - -
-for (; first != last; ++first)
-  append(*first);
-
- -Requires: The BlockInputIterator type must be a -model of LegacyInputIterator -and the value_type must be the same type as -Block.
- Throws: An allocation error if memory is exhausted -(std::bad_alloc if -Allocator=std::allocator).
- - -
-
-dynamic_bitset& operator&=(const dynamic_bitset& rhs)
-
- -Requires: this->size() == rhs.size().
- Effects: Bitwise-AND all the bits in rhs with -the bits in this bitset. This is equivalent to: - -
-for (size_type i = 0; i != this->size(); ++i)
-  (*this)[i] = (*this)[i] & rhs[i];
-
- -Returns: *this.
- Throws: nothing. - -
-
-dynamic_bitset& operator|=(const dynamic_bitset& rhs)
-
- -Requires: this->size() == rhs.size().
- Effects: Bitwise-OR's all the bits in rhs with -the bits in this bitset. This is equivalent to: - -
-for (size_type i = 0; i != this->size(); ++i)
-  (*this)[i] = (*this)[i] | rhs[i];
-
- -Returns: *this.
- Throws: nothing. - -
-
-dynamic_bitset& operator^=(const dynamic_bitset& rhs)
-
- -Requires: this->size() == rhs.size().
- Effects: Bitwise-XOR's all the bits in rhs with -the bits in this bitset. This is equivalent to: - -
-for (size_type i = 0; i != this->size(); ++i)
-  (*this)[i] = (*this)[i] ^ rhs[i];
-
- -Returns: *this.
- Throws: nothing. - -
-
-dynamic_bitset& operator-=(const dynamic_bitset& rhs)
-
- -Requires: this->size() == rhs.size().
- Effects: Computes the set difference of this bitset and -the rhs bitset. This is equivalent to: - -
-for (size_type i = 0; i != this->size(); ++i)
-  (*this)[i] = (*this)[i] && !rhs[i];
-
- -Returns: *this.
- Throws: nothing. - -
-
-dynamic_bitset& operator<<=(size_type n)
-
- -Effects: Shifts the bits in this bitset to the left by -n bits. For each bit in the bitset, the bit at position -pos takes on the previous value of the bit at position pos - -n, or zero if no such bit exists.
- Returns: *this.
- Throws: nothing. - -
-
-dynamic_bitset& operator>>=(size_type n)
-
- -Effects: Shifts the bits in this bitset to the right by -n bits. For each bit in the bitset, the bit at position -pos takes on the previous value of bit pos + n, -or zero if no such bit exists.
- Returns: *this.
- Throws: nothing. - -
-
-dynamic_bitset operator<<(size_type n) const
-
- -Returns: a copy of *this shifted to the left by -n bits. For each bit in the returned bitset, the bit at -position pos takes on the value of the bit at position pos - -n of this bitset, or zero if no such bit exists.
- Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-dynamic_bitset operator>>(size_type n) const
-
- -Returns: a copy of *this shifted to the right by -n bits. For each bit in the returned bitset, the bit at -position pos takes on the value of the bit at position pos + -n of this bitset, or zero if no such bit exists.
- Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-dynamic_bitset& set()
-
- -Effects: Sets every bit in this bitset to 1.
-Returns: *this
-Throws: nothing. - -
-
-dynamic_bitset& flip()
-
- -Effects: Flips the value of every bit in this bitset.
-Returns: *this
-Throws: nothing. - -
-
-dynamic_bitset operator~() const
-
- -Returns: a copy of *this with all of its bits -flipped.
-Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-dynamic_bitset& reset()
-
- -Effects: Clears every bit in this bitset.
-Returns: *this
-Throws: nothing. - -
-
-dynamic_bitset& set(size_type n, size_type len, bool val);
-
- -Precondition: n + len < this->size().
-Effects: Sets every bit indexed from n to -n + len - 1 inclusively if val is true, and -clears them if val is false.
-Returns: *this - -
-
-dynamic_bitset& set(size_type n, bool val = true)
-
- -Precondition: n < this->size().
- Effects: Sets bit n if val is -true, and clears bit n if val is -false.
- Returns: *this - -
-
-dynamic_bitset& reset(size_type n, size_type len);
-
- -Precondition: n + len < this->size().
-Effects: Clears every bit indexed from n to -n + len - 1 inclusively.
-Returns: *this - -
-
-dynamic_bitset& reset(size_type n)
-
- -Precondition: n < this->size().
-Effects: Clears bit n.
-Returns: *this - -
-
-dynamic_bitset& flip(size_type n, size_type len)
-
- -Precondition: n + len < this->size().
-Effects: Flips every bit indexed from n to -n + len - 1 inclusively.
-Returns: *this - -
-
-dynamic_bitset& flip(size_type n)
-
- -Precondition: n < this->size().
-Effects: Flips bit n.
-Returns: *this - -
-
-size_type size() const
-
- -Returns: the number of bits in this bitset.
-Throws: nothing. - -
-
-size_type num_blocks() const
-
- -Returns: the number of blocks in this bitset.
-Throws: nothing. - -
-
-size_type max_size() const;
-
- -Returns: the maximum size of a dynamic_bitset -object having the same type as *this. Note that if -any dynamic_bitset operation causes size() to -exceed max_size() then the behavior is undefined. -

[The semantics of this function could change slightly -when lib issue 197 will be closed]
- -
-
-bool empty() const;
-
- -Returns: true if this->size() == 0, false -otherwise. Note: not to be confused with none(), that has -different semantics. - -
-
-size_type capacity() const;
-
- -Returns: The total number of elements that *this can hold without requiring -reallocation.
-Throws: nothing. - -
-
-void reserve(size_type num_bits);
-
- -Effects: A directive that informs the bitset of a planned change in size, so that it can -manage the storage allocation accordingly. After reserve(), capacity() is greater or equal to the -argument of reserve() if reallocation happens; and equal to the previous value of capacity() otherwise. -Reallocation happens at this point if and only if the current capacity is less than the argument of -reserve().
-Note: It does not change the size() of the bitset.
-Postcondtitions: this->capacity() >= num_bits.
-Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-void shrink_to_fit();
-
- -Effects: shrink_to_fit() is a request to reduce memory use by removing unused capacity.
-Note: It does not change the size() of the bitset.
-Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-size_type count() const
-
- -Returns: the number of bits in this bitset that are -set.
-Throws: nothing. - -
-
-bool all() const
-
- -Returns: true if all bits in this bitset are set or -if size() == 0, and otherwise returns false.
-Throws: nothing. - -
-
-bool any() const
-
- -Returns: true if any bits in this bitset are set, -and otherwise returns false.
-Throws: nothing. - -
-
-bool none() const
-
- -Returns: true if no bits are set, and otherwise -returns false.
-Throws: nothing. - -
-
-reference at(size_type n)
-
- -Returns: The same as operator[](n).
-Throws: std::out_of_range if that n is not within the range of the bitset. - -
-
-bool at(size_type n) const
-
- -Returns: The same as operator[](n).
-Throws: std::out_of_range if that n is not within the range of the bitset. - -
-
-bool test(size_type n) const
-
- -Precondition: n < this->size().
- Returns: true if bit n is set and -false is bit n is 0. - -
-
-bool test_set(size_type n, bool val = true)
-
- -Precondition: n < this->size().
- Effects: Sets bit n if val is -true, and clears bit n if val is -false.
- Returns: true if the previous state of bit -n was set and false is bit n is 0. - -
-
-reference operator[](size_type n)
-
- -Precondition: n < this->size().
- Returns: a reference to bit n. Note -that reference is a proxy class with an assignment -operator and a conversion to bool, which allows you to -use operator[] for assignment. That is, you can write -both x = b[n] and b[n] = x. However, in many -other respects the proxy is not the same as the true reference -type bool&. - -
-
-bool operator[](size_type n) const
-
- -Precondition: n < this->size().
-Returns: The same as test(n). - -
-
-unsigned long to_ulong() const
-
- -Returns: The numeric value corresponding to the bits in *this. -
-Throws: std::overflow_error if that value is too large to -be represented in an unsigned long, i.e. if *this has -any non-zero bit at a position >= -std::numeric_limits<unsigned long>::digits. - -
-
-bool is_subset_of(const dynamic_bitset& a) const
-
- -Requires: this->size() == a.size()
-Returns: true if this bitset is a subset of bitset -a. That is, it returns true if, for every bit that is -set in this bitset, the corresponding bit in bitset a is -also set. Otherwise this function returns false.
-Throws: nothing. - -
-
-bool is_proper_subset_of(const dynamic_bitset& a) const
-
- -Requires: this->size() == a.size()
-Returns: true if this bitset is a proper subset of bitset -a. That is, it returns true if, for every bit that is -set in this bitset, the corresponding bit in bitset a is -also set and if this->count() < a.count(). -Otherwise this function returns false.
-Throws: nothing. - -
-
-bool intersects(const dynamic_bitset& a) const
-
- -Requires: this->size() == a.size()
-Returns: true if this bitset and a intersect. -That is, it returns true if, there is a bit which is set in this -bitset, such that the corresponding bit in bitset a is -also set. Otherwise this function returns false.
-Throws: nothing. - -
-
-size_type find_first() const;
-
- -Returns: the lowest index i such as bit i -is set, or npos if *this has no on bits. - -
-
-size_type find_first(size_type pos) const;
-
- -Returns: the lowest index i greater or equal to -offset such as bit i is set, or npos if -no such index exists. - -
-
-size_type find_next(size_type pos) const;
-
- -Returns: the lowest index i greater than -pos such as bit i is set, or npos if -no such index exists. - -
-
-bool operator==(const dynamic_bitset& rhs) const
-
- -Returns: true if this->size() == -rhs.size() and if for all i in the range -[0,rhs.size()), (*this)[i] == rhs[i]. Otherwise -returns false.
- Throws: nothing.
- (Required by EqualityComparable.) - -
-
-bool operator!=(const dynamic_bitset& rhs) const
-
- -Returns: !((*this) == rhs)
-Throws: nothing.
-(Required by EqualityComparable.) - -
-
-bool operator<(const dynamic_bitset& rhs) const
-
- -Returns: true if this bitset is lexicographically -less than rhs, and returns false otherwise. -
-Throws: nothing.
-(Required by LessThanComparable.) - -
-
-bool operator>(const dynamic_bitset& rhs) const
-
- -Returns: !((*this) < rhs || (*this) == -rhs)
-Throws: nothing.
-(Required by LessThanComparable.) - -
-
-bool operator<=(const dynamic_bitset& rhs) const
-
- -Returns: (*this) < rhs || (*this) == rhs
-Throws: nothing.
-(Required by LessThanComparable.) - -
-
-bool operator>=(const dynamic_bitset& rhs) const
-
- -Returns: (*this) > rhs || (*this) == rhs
-Throws: nothing.
-(Required by LessThanComparable.) - -
-

Non-member functions

- -
-
-dynamic_bitset operator&(const dynamic_bitset& a, const dynamic_bitset& b)
-
- -Requires: a.size() == b.size()
-Returns: A new bitset that is the bitwise-AND of the -bitsets a and b.
-Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-dynamic_bitset operator|(const dynamic_bitset& a, const dynamic_bitset& b)
-
- -Requires: a.size() == b.size()
-Returns: A new bitset that is the bitwise-OR of the -bitsets a and b.
-Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-dynamic_bitset operator^(const dynamic_bitset& a, const dynamic_bitset& b)
-
- -Requires: a.size() == b.size()
-Returns: A new bitset that is the bitwise-XOR of the -bitsets a and b.
-Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-dynamic_bitset operator-(const dynamic_bitset& a, const dynamic_bitset& b)
-
- -Requires: a.size() == b.size()
-Returns: A new bitset that is the set difference of the -bitsets a and b.
-Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). - -
-
-template <typename CharT, typename Alloc>
-void to_string(const dynamic_bitset<Block, Allocator>& b,
-               std::basic_string<Char,Traits,Alloc>& s)
-
- -Effects: Copies a representation of b into the -string s. A character in the string is '1' if -the corresponding bit is set, and '0' if it is not. -Character position i in the string corresponds to bit -position b.size() - 1 - i.
- Throws: If memory is exhausted, the string will throw an -allocation error.
- Rationale: This function is not a member function taking -zero arguments and returning a string for a couple reasons. -First, this version can be slighly more efficient because the -string is not copied (due to being passed by value). Second, as a -member function, to allow for flexibility with regards to the -template parameters of basic_string, the member function -would require explicit template parameters. Few C++ programmers -are familiar with explicit template parameters, and some C++ -compilers do not handle them properly. - -
-
-template <typename Block, typename Alloc, typename BlockOutputIterator>
-void to_block_range(const dynamic_bitset<Block, Alloc>& b, BlockOutputIterator result)
-
- -Effects: Writes the bits of the bitset into the iterator -result a block at a time. The first block written -represents the bits in the position range -[0,bits_per_block) in the bitset, the second block -written the bits in the range -[bits_per_block,2*bits_per_block), and so on. For each -block bval written, the bit (bval >> i) & -1 corresponds to the bit at position (b * bits_per_block -+ i) in the bitset.
- Requires: The type BlockOutputIterator must be a -model of LegacyOutputIterator -and its value_type must be the same type as -Block. Further, the size of the output range must be -greater or equal b.num_blocks(). - -
-
-template <typename BlockIterator, typename Block, typename Alloc>
-void from_block_range(BlockIterator first,
-    BlockIterator last, const dynamic_bitset<Block, Alloc>& b)
-
- -Effects: Reads blocks from the iterator range into the -bitset.
- Requires: The type BlockIterator must be a model -of LegacyInputIterator -and its value_type must be the same type as -Block. The size of the iterator range must be less or -equal to b.num_blocks(). - -
-
-template <typename Char, typename Traits, typename Block, typename Alloc>
-basic_ostream<Char, Traits>&
-operator<<(basic_ostream<Char, Traits>& os, const dynamic_bitset<Block, Alloc>& b)
-
- -Effects: Inserts a textual representation of b into the stream -os (highest bit first). Informally, the output is the same as doing - -
-std::basic_string<Char, Traits> s;
-boost::to_string(x, s):
-os << s;
-
- -except that the stream inserter takes into accout the locale imbued into -os, which boost::to_string() can't do. Here is a more -precise specification, given in terms of "as if" rule: first, for each -valid position i into the bitset b let's put: - - character_of(b[i)]) = b[i]? os.widen('1') : os.widen('0'); - -Let also s be a std::basic_string<Char, Traits> -object, having length b.size() and such as, for each i -in [0, b.size()), - - s[i] is character_of(b[i]) - -Then, the output, the effects on os and the exception behavior -is the same as outputting the object s to os (same -width, same exception mask, same padding, same setstate() logic) -
-Returns: os
-Throws: std::ios_base::failure if there is a -problem writing to the stream. - -
-
-template <typename Char, typename Traits, typename Block, typename Alloc>
-std::basic_istream<Char,Traits>&
-operator>>(std::basic_istream<Char,Traits>& is, dynamic_bitset<Block, Alloc>& b)
-
- -Effects: Extracts a dynamic_bitset from an input stream. -

- Definitions:

- Let Tr be the traits_type of is. Then: -
    -
  1. - A (non-eof) character c extracted from is - is a bitset digit if and only if either Tr::eq(c, is.widen('0')) or - Tr::eq(c, is.widen('1')) return true. -
  2. -
  3. If c is a bitset digit, it's corresponding bit value is 0 if - Tr::eq(c, is.widen('0')) is true, 1 otherwise. -
  4. -
- -The function begins by constructing a sentry object k as if k -were constructed by - - typename std::basic_istream<Char, Traits>::sentry k(is). - -If bool(k) is true, it calls b.clear() -then attempts to extract characters from is. For each character c -that is a bitset digit the corresponding bit value is -appended to the less significant end of b (appending may throw). -If is.width() is greater than zero and smaller than b.max_size() -then the maximum number n of bits appended is is.width(); -otherwise n = b.max_size(). - -Unless the extractor is exited via an exception, characters are extracted (and -corresponding bits appended) until any of the following occurs:
- -
    -
  • n bits are stored into the bitset;
  • -
  • end-of-file, or an error, occurs on the input sequence;
  • -
  • the next available input character isn't a bitset digit
  • -
-
If no exception caused the function to exit then is.width(0) is - called, regardless of how many characters were actually extracted. The - sentry object k is destroyed. -
-
If the function extracts no characters[???], it calls is.setstate(std::ios::failbit), - which may throw std::ios_base::failure. - - -
------ - - -
-Throws: An allocation error if memory is exhausted -(std::bad_alloc if Allocator=std::allocator). -A std::ios_base::failure if there is a problem reading -from the stream. - -
-

Exception guarantees

- -All of dynamic_bitset functions offer at least the basic -exception guarantee. - -
-

Changes from previous version(s)

- -

Changes in Boost 1.56.0

-
    -
  • Support for C++11 move constructors.
  • -
  • Warning fixes on MSVC 2013.
  • -
  • Support for C++11 minimal allocators.
  • -
  • Add noexcept specifications.
  • -
- -

Changes in Boost 1.37.0

-
    -
  • The constructor from a block range implements a "do the right thing" -behavior, a la standard sequences.
  • -
- - -

Changes from Boost 1.31.0

-
    -
  • -The stream extractor has completely different semantics: as natural -for a dynamic structure, it now expands the bitset as needed during -extraction. The new behaviour mimics that of the basic_string -extractor but there are some differences the user should be aware of; -so, please, check the documentation. (One -difference concerns the case where stream.width() > - bitset.max_size() > 0. In that circumstance the -extractor of dynamic_bitset never attempts to extract more -than max_size() characters, whereas the extractor of -basic_string goes on and, on conforming implementations, -eventually throws a length_error exception. Note: That's what -the standard mandates -see especially library - issue 83- but not all implementations conform) -

    -The stream extractor is now also "exception-aware" in the sense that -it works correctly when setting exception masks on the stream. -

    -
  • -
  • -Several member functions (empty(), find_first() -, find_next(), get_allocator(), intersects() -, max_size() ) -have been added. -
  • -
  • -The constructor from basic_string has a new parameter that was totally -forgotten before. -
  • - -
-Technicalities and minor changes -
    -
  • -The class reference has been reimplemented so that -dynamic_bitset's references behave more like references to standard -container elements. In particular it is now guaranteed that they -cannot be invalidated from a standard library swap() function -applied to their corresponding dynamic_bitsets. -
  • -
-General improvements -
    -
  • -Several optimizations to member and non-member functions and to the -nested class reference. -
  • -
- -
- -

Acknowledgements

- -

We would like to thank the Boost community for putting in the -time to review and accept this library. This library is much -better than it ever would have been due to all the suggestions -from Boost members. We especially thank Matt Marcus for taking on -the task of review manager. Also, a special thanks goes to -James Kanze for his invaluable help with the internationalization -issues.

- - - - - - - - - - - - - - - - - -
Copyright © 2001Jeremy -Siek, Indiana University (jsiek@osl.iu.edu)
Chuck Allison, Senior Editor, -C/C++ Users Journal (cda@freshsources.com)
Copyright © 2003-2004, 2008 Gennaro Prota - (firstName.lastName -at- gmail.com)
Copyright © 2014Ahmed Charles (acharles@outlook.com)
Copyright © 2014Glen Fernandes (glenjofe@gmail.com)
Copyright © 2014Riccardo Marcangelo (ricky.65@outlook.com)
-
-
- Distributed under the Boost Software License, Version 1.0. - (See accompanying file LICENSE_1_0.txt - or copy at -http://www.boost.org/LICENSE_1_0.txt) -
- - -
-
-
-
-
-
- - - - - - diff --git a/include/boost/dynamic_bitset/dynamic_bitset.hpp b/include/boost/dynamic_bitset/dynamic_bitset.hpp index eb19e91..1930997 100644 --- a/include/boost/dynamic_bitset/dynamic_bitset.hpp +++ b/include/boost/dynamic_bitset/dynamic_bitset.hpp @@ -46,6 +46,27 @@ namespace boost { +//! The `dynamic_bitset` template represents a set of bits. +//! +//! \par Template parameters +//! - `Block` +//! The integer type in which the bits are stored. Defaults to +//! `unsigned long`. +//! +//! - `Allocator` +//! The allocator type used for all internal memory management. +//! Defaults to `std::allocator< Block >`. +//! +//! \par Concepts modeled +//! DefaultConstructible, CopyConstructible, CopyAssignable, +//! MoveConstructible, MoveAssignable, EqualityComparable, +//! LessThanComparable. +//! +//! \par Type requirements +//! `Block` is a cv-unqualified unsigned integer type other than +//! `bool`. `Allocator` satisfies the standard requirements for an +//! allocator. +// --------------------------------------------------------------------------- template< typename Block, typename Allocator > class dynamic_bitset { @@ -53,39 +74,155 @@ class dynamic_bitset typedef std::vector< Block, Allocator > buffer_type; public: + //! The same type as `Block`. + // ----------------------------------------------------------------------- typedef Block block_type; + + //! The same type as `Allocator`. + // ----------------------------------------------------------------------- typedef Allocator allocator_type; + + //! An unsigned integral type that can represent the size of the + //! bitset. See \ref size(). + // ----------------------------------------------------------------------- typedef std::size_t size_type; + typedef typename buffer_type::size_type block_width_type; + //! The number of bits the type `Block` uses to represent + //! values, excluding any padding bits. Numerically equal to + //! `std::numeric_limits< Block >::digits`. + // ----------------------------------------------------------------------- BOOST_STATIC_CONSTANT( block_width_type, bits_per_block = ( std::numeric_limits< Block >::digits ) ); + + //! The maximum value of `size_type`. + // ----------------------------------------------------------------------- BOOST_STATIC_CONSTANT( size_type, npos = static_cast< size_type >( -1 ) ); - // A proxy class to simulate lvalues of bit type. - // + //! A proxy class to simulate lvalues of bit type. + //! + //! This class exists only as a helper class for + //! `dynamic_bitset`'s `operator[]`. The following list + //! describes the valid operations on the reference type. Assume + //! that `b` is an instance of `dynamic_bitset`, `i`, `j` are of + //! `size_type` and in the range `[0, b.size())`. Also, note + //! that when we write `b[ i ]` we mean an object of type + //! `reference` that was initialized from `b[ i ]`. The variable + //! `x` is a `bool`. + //! + //! - `(bool)b[ i ]` + //! + //! Returns the i-th bit of `b`. + //! + //! - `(bool)~ b[ i ]` + //! + //! Returns the opposite of the ith bit of `b`. + //! + //! - `b[ i ].flip()` + //! + //! Flips the i-th bit of `b` and returns `b[ i ]`. + //! + //! - `x = b[ i ]` + //! + //! Assigns the i-th bit of `b` to `x`. + //! + //! - `b[ i ] = x` + //! + //! Sets the i-th bit of `b` to the value of `x` and returns + //! `b[ i ]`. + //! + //! - `b[ i ] = b[ j ]` + //! + //! Sets the i-th bit of `b` to the value of the j-th bit of + //! `b` and returns `b[ i ]`. + //! + //! - `b[ i ] |= x` + //! + //! Does an OR of the i-th bit of `b` with the value of `x` + //! and returns `b[ i ]`. + //! + //! - `b[ i ] &= x` + //! + //! Does an AND of the i-th bit of `b` with the value of `x` + //! and returns `b[ i ]`. + //! + //! - `b[ i ] ^= x` + //! + //! Does a XOR of the i-th bit of `b` with the value of `x` + //! and returns `b[ i ]`. + //! + //! - `b[ i ] -= x` + //! + //! If `x` is `true`, clears the i-th bit of `b`. Returns `b[ + //! i ]`. + //! + //! - `b[ i ] |= b[ j ]` + //! + //! Does an OR of the i-th bit of `b` with the j-th bit of `b` + //! and returns `b[ i ]`. + //! + //! - `b[ i ] &= b[ j ]` + //! + //! Does an AND of the i-th bit of `b` with the j-th bit of + //! `b` and returns `b[ i ]`. + //! + //! - `b[ i ] ^= b[ j ]` + //! + //! Does a XOR of the i-th bit of `b` with the j-th bit of `b` + //! and returns `b[ i ]`. + //! + //! - `b[ i ] -= b[ j ]` + //! + //! If the j-th bit of `b` is set, clears the i-th bit of `b`. + //! Returns `b[ i ]`. + // ----------------------------------------------------------------------- class reference { friend class dynamic_bitset< Block, Allocator >; - // the one and only non-copy ctor + //! The one and only non-copy ctor + // ------------------------------------------------------------------- reference( block_type & b, block_width_type pos ); - void operator&(); // left undefined + //! Left undefined. + // ------------------------------------------------------------------- + void operator&(); public: - // copy constructor: compiler generated - + //! See the class description. + // ------------------------------------------------------------------- operator bool() const; + + //! See the class description. + // ------------------------------------------------------------------- bool operator~() const; + //! See the class description. + // ------------------------------------------------------------------- reference & flip(); + //! See the class description. + // ------------------------------------------------------------------- reference & operator=( bool x ); + + //! See the class description. + // ------------------------------------------------------------------- reference & operator=( const reference & rhs ); + //! See the class description. + // ------------------------------------------------------------------- reference & operator|=( bool x ); + + //! See the class description. + // ------------------------------------------------------------------- reference & operator&=( bool x ); + + //! See the class description. + // ------------------------------------------------------------------- reference & operator^=( bool x ); + + //! See the class description. + // ------------------------------------------------------------------- reference & operator-=( bool x ); private: @@ -98,116 +235,782 @@ public: void do_assign( bool x ); }; + //! The type bool. + // ----------------------------------------------------------------------- typedef bool const_reference; - // constructors, etc. + //! Constructs a bitset of size zero. The allocator for this + //! bitset is a default-constructed object of type `Allocator`. + //! + //! \par Postconditions + //! `this->size() == 0`. + //! + //! (Required by DefaultConstructible.) + // ----------------------------------------------------------------------- dynamic_bitset(); + //! Constructs a bitset of size zero. A copy of the `alloc` + //! object will be used in subsequent bitset operations such as + //! `resize()` to allocate memory. + //! + //! \par Postconditions + //! `this->size() == 0` + // ----------------------------------------------------------------------- explicit dynamic_bitset( const Allocator & alloc ); + //! Constructs a bitset from an integer. + //! + //! The first `M` bits (where `M = min( num_bits, + //! std::numeric_limits< unsigned long >::digits )`) are + //! initialized to the corresponding bits in `value` and all + //! other bits, if any, to zero. A copy of the `alloc` object + //! will be used in subsequent bitset operations such as + //! `resize()` to allocate memory. Note that, e.g., the + //! following + //! + //! \code + //! dynamic_bitset b<>( 16, 7 ); + //! \endcode + //! + //! will match the constructor from an iterator range (not this + //! one), but the underlying implementation will still "do the + //! right thing" and construct a bitset of 16 bits, from the + //! value 7. + //! + //! \par Postconditions: + //! - `this->size() == num_bits` + //! - For all i in the range `[0, M)`, `( *this )[ i ] == ( + //! value >> i ) & 1`. + //! - For all i in the range `[M, num_bits)`, `( *this )[ i ] == + //! false`. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + // ----------------------------------------------------------------------- explicit dynamic_bitset( size_type num_bits, unsigned long value = 0, const Allocator & alloc = Allocator() ); - // WARNING: you should avoid using this constructor. - // - // A conversion from string is, in most cases, formatting, - // and should be performed by using operator>>. - // - // NOTE: - // Leave the parentheses around std::basic_string::npos. - // g++ 3.2 requires them and probably the standard will - see core issue 325 - // NOTE 2: - // split into two constructors because of bugs in MSVC 6.0sp5 with STLport - + //! Constructs a bitset from a string of 0's and 1's. The size + //! of the bitset is `num_bits` if `num_bits != npos`, otherwise + //! `rlen = min( n, s.size() - pos )`. The first `M = min( + //! num_bits, rlen )` bits are initialized to the corresponding + //! characters in `s`. Note that the highest character position + //! in `s`, not the lowest, corresponds to the least significant + //! bit. So, for example, `dynamic_bitset( std::string( "1101" ) + //! )` is the same as `dynamic_bitset( 13ul )`. + //! + //! \pre + //! `pos <= s.size()` and the characters used to initialize the + //! bits are '0' or '1'. + // ----------------------------------------------------------------------- template< typename CharT, typename Traits, typename Alloc > - dynamic_bitset( const std::basic_string< CharT, Traits, Alloc > & s, typename std::basic_string< CharT, Traits, Alloc >::size_type pos, typename std::basic_string< CharT, Traits, Alloc >::size_type n, size_type num_bits = npos, const Allocator & alloc = Allocator() ); + dynamic_bitset( const std::basic_string< CharT, Traits, Alloc > & s, typename std::basic_string< CharT, Traits, Alloc >::size_type pos = 0, typename std::basic_string< CharT, Traits, Alloc >::size_type n = (std::basic_string::npos), size_type num_bits = npos, const Allocator & alloc = Allocator() ); - template< typename CharT, typename Traits, typename Alloc > - explicit dynamic_bitset( const std::basic_string< CharT, Traits, Alloc > & s, typename std::basic_string< CharT, Traits, Alloc >::size_type pos = 0 ); - - // The first bit in *first is the least significant bit, and the - // last bit in the block just before *last is the most significant bit. + //! Constructs a bitset from a range of blocks or from an + //! integer. + //! + //! If this constructor is called with a type + //! `BlockInputIterator` which is actually an integral type, the + //! library behaves as if the constructor from `unsigned long` + //! were called, with arguments `static_cast< size_type >( first + //! )`, `last` and `alloc`, in that order. + //! + //! \par Example + //! Given: + //! + //! \code + //! dynamic_bitset< unsigned short > b( 8, 7 ); + //! \endcode + //! + //! `b` is constructed as if by calling the constructor: + //! + //! \code + //! dynamic_bitset(size_type num_bits, + //! unsigned long value = 0, + //! const Allocator& alloc = Allocator()) + //! \endcode + //! + //! with arguments: + //! + //! \code + //! static_cast< dynamic_bitset< unsigned short >::size_type >( 8 ), + //! 7, + //! Allocator() + //! \endcode + //! + //! Note: + //! At the time of writing (October 2008) this is aligned with + //! the proposed resolution for library issue 438. That is a + //! post C++03 change, and is currently in the working paper for + //! C++0x. Informally speaking, the critical changes with + //! respect to C++03 are the drop of a `static_cast` on the + //! second argument, and more leeway as to when the templated + //! constructor should have the same effect as the `(size, + //! value)` one: Only when `InputIterator` is an integral type, + //! in C++03; when it is either an integral type or any other + //! type that the implementation might detect as impossible to + //! be an input iterator, with the proposed resolution. For the + //! purposes of dynamic_bitset we limit ourselves to the first + //! of these two changes. + //! + //! Otherwise (i.e. if the template argument is not an integral + //! type), constructs a bitset based on a range of blocks. Let + //! `*first` be block number 0, `*++first` block number 1, etc. + //! Block number `b` is used to initialize the bits of the + //! dynamic_bitset in the position range `[b * bits_per_block, ( + //! b + 1 ) * bits_per_block)`. For each block number `b` with + //! value `bval`, the bit `( bval >> i ) & 1` corresponds to the + //! bit at position `b * bits_per_block + i` in the bitset + //! (where i goes through the range `[0, bits_per_block)`). + //! \pre + //! `BlockInputIterator` must be either an integral type or a + //! model of LegacyInputIterator + //! whose `value_type` is the same type as `Block`. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + // ----------------------------------------------------------------------- template< typename BlockInputIterator > dynamic_bitset( BlockInputIterator first, BlockInputIterator last, const Allocator & alloc = Allocator() ); - // copy constructor + //! Copy constructor. + //! + //! Constructs a bitset that is a copy of the bitset `b`. The + //! allocator for this bitset is a copy of the allocator of `b`. + //! + //! \par Postconditions + //! For all i in the range `[0, b.size())`, `( *this )[ i ] == + //! b[ i ]`. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + //! + //! (Required by CopyConstructible.) + // ----------------------------------------------------------------------- dynamic_bitset( const dynamic_bitset & b ); - ~dynamic_bitset(); - - void swap( dynamic_bitset & b ) BOOST_NOEXCEPT; + //! Copy assignment operator. + //! + //! This bitset becomes a copy of the bitset `b`. + //! + //! \par Postconditions + //! For all `i` in the range `[0, x.size())`, `( *this )[ i ] == + //! b[ i ]`. + //! + //! \return + //! `*this`. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + //! (Required by CopyAssignable.) + // ----------------------------------------------------------------------- dynamic_bitset & operator=( const dynamic_bitset & b ); + //! Destructor. + //! + //! Releases the memory associated with this bitset and destroys + //! the bitset object itself. + // ----------------------------------------------------------------------- + ~dynamic_bitset(); + + //! Swaps the contents of this bitset and bitset `b`. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- + void swap( dynamic_bitset & b ) BOOST_NOEXCEPT; + #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + //! Move constructor. + //! + //! Constructs a bitset that is the same as the bitset `src`, + //! while using the resources from `src`. The allocator for this + //! bitset is moved from the allocator in `src`. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + // ----------------------------------------------------------------------- dynamic_bitset( dynamic_bitset && src ); + + //! Move assignment operator. + //! + //! This bitset becomes the same as the bitset `src`, while + //! using the resources from `src`. + //! + //! \return + //! `*this`. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- dynamic_bitset & operator=( dynamic_bitset && src ); #endif // BOOST_NO_CXX11_RVALUE_REFERENCES + //! Returns a copy of the allocator object used to construct + //! `*this`. + // ----------------------------------------------------------------------- allocator_type get_allocator() const; - // size changing operations + //! Changes the number of bits of the bitset to `num_bits`. If + //! `num_bits >= size()` then the bits in the range `[0, + //! size())` remain the same, and the bits in `[size(), + //! num_bits]` are all set to `value`. If `num_bits < size()` + //! then the bits in the range `[0, num_bits)` stay the same + //! (and the remaining bits are discarded). + // ----------------------------------------------------------------------- void resize( size_type num_bits, bool value = false ); + + //! Clears the bitset, i.e. makes its size zero. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- void clear(); + + //! Increases the size of the bitset by one, and sets the value + //! of the new most significant bit to `bit`. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + // ----------------------------------------------------------------------- void push_back( bool bit ); + + //! Decreases the size of the bitset by one, removing the most + //! significant bit. + //! + //! \pre + //! `! this->empty()` + // ----------------------------------------------------------------------- void pop_back(); + + //! Appends the bits in `block` to this bitset (appends to the + //! most significant end). This increases the size of the bitset + //! by `bits_per_block`. Let `s` be the old size of the bitset, + //! then for `i` in the range `[0, bits_per_block)`, the bit at + //! position `s + i` is set to `( block >> i ) & 1`. + // ----------------------------------------------------------------------- void append( Block block ); + //! Appends a range of block to `*this`. + //! + //! This member provides the same end result as the following + //! code, but is typically more efficient. + //! + //! \code + //! for (; first != last; ++first) { + //! append( *first ); + //! } + //! \endcode + //! + //! \pre + //! The `BlockInputIterator` type must be a model of + //! LegacyInputIterator + //! and its value_type must be the same type as Block. + // ----------------------------------------------------------------------- template< typename BlockInputIterator > void append( BlockInputIterator first, BlockInputIterator last ); // strong guarantee - // bitset operations + //! Bitwise-ANDs all the bits in this bitset with the bits in + //! `b`. + //! + //! This is equivalent to: + //! \code + //! for ( size_type i = 0; i != this->size(); ++ i ) { + //! ( *this )[ i ] = ( *this )[ i ] & b[ i ]; + //! } + //! \endcode + //! + //! \pre + //! `this->size() == b.size()` + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- dynamic_bitset & operator&=( const dynamic_bitset & b ); + + //! Bitwise-ORs all the bits in this bitset with the bits in + //! `b`. + //! + //! This is equivalent to: + //! \code + //! for ( size_type i = 0; i != this->size(); ++ i ) { + //! ( *this )[ i ] = ( *this )[ i ] | b[ i ]; + //! } + //! \endcode + //! + //! \pre + //! `this->size() == b.size()` + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- dynamic_bitset & operator|=( const dynamic_bitset & b ); + + //! Bitwise-XORs all the bits in this bitset with the bits in + //! `b`. + //! + //! This is equivalent to: + //! \code + //! for ( size_type i = 0; i != this->size(); ++ i ) { + //! ( *this )[ i ] = ( *this )[ i ] ^ b[ i ]; + //! } + //! \endcode + //! + //! \pre + //! `this->size() == b.size()`. + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- dynamic_bitset & operator^=( const dynamic_bitset & b ); + + //! Computes the set difference of this bitset and the `b` + //! bitset. + //! + //! This is equivalent to: + //! \code + //! for ( size_type i = 0; i != this->size(); ++ i ) { + //! ( *this )[ i ] = ( *this )[ i ] && ! b[ i ]; + //! } + //! \endcode + //! + //! \pre + //! `this->size() == b.size()`. + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- dynamic_bitset & operator-=( const dynamic_bitset & b ); + + //! Shifts the bits in this bitset to the left by `n` positions. + //! For each bit in the bitset, the bit at position `pos` takes + //! on the previous value of the bit at position `pos - n`, or + //! zero if no such bit exists. + //! + //! \return + //! `*this`. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- dynamic_bitset & operator<<=( size_type n ); + + //! Shifts the bitset in this bitset to the right by `n` + //! positions. For each bit in the bitset, the bit at position + //! `pos` takes on the previous value of the bit at position + //! `pos + n`, or zero if no such bit exists. + //! + //! \return + //! `*this`. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- dynamic_bitset & operator>>=( size_type n ); + + //! Returns a shifted copy of `*this`. + //! + //! \return + //! A copy of `*this` shifted to the left by `n` positions. For + //! each bit in the returned bitset, the bit at position `pos` + //! takes on the value of the bit at position `pos - n` of this + //! bitset, or zero if no such bit exists. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + // ----------------------------------------------------------------------- dynamic_bitset operator<<( size_type n ) const; + + //! Returns a shifted copy of `*this`. + //! + //! \return + //! A copy of `*this` shifted to the right by `n` positions. For + //! each bit in the returned bitset, the bit at position `pos` + //! takes on the value of the bit at position `pos + n` of this + //! bitset, or zero if no such bit exists. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + // ----------------------------------------------------------------------- dynamic_bitset operator>>( size_type n ) const; - // basic bit operations - dynamic_bitset & set( size_type n, size_type len, bool val /* = true */ ); // default would make it ambiguous - dynamic_bitset & set( size_type n, bool val = true ); + //! Sets the bits in the range `[pos, pos + len)` to `val`. + //! + //! If `len` is zero, does nothing. Otherwise, sets all the bits + //! in this bitset which have a position in `[pos, pos + len - + //! 1]` to `val`. + //! + //! \pre + //! `pos + len <= this->size()`. + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- + dynamic_bitset & set( size_type pos, size_type len, bool val /* = true */ ); // default would make it ambiguous + + //! Sets the bit at position `pos` in this bitset to `val`. + //! + //! \pre + //! `pos < this->size()`. + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- + dynamic_bitset & set( size_type pos, bool val = true ); + + //! Sets all the bits in this bitset. + //! + //! \return + //! `*this`. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- dynamic_bitset & set(); - dynamic_bitset & reset( size_type n, size_type len ); - dynamic_bitset & reset( size_type n ); + + //! If `len` is zero, does nothing. Otherwise, resets all the + //! bits in this bitset which have a position in `[pos, pos + + //! len - 1]`. + //! + //! \pre + //! `pos + len <= this->size()`. + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- + dynamic_bitset & reset( size_type pos, size_type len ); + + //! Resets the bit in this bitset at position `pos`. + //! + //! \pre + //! `pos < this->size()`. + //! + //! \return + //! `this`. + // ----------------------------------------------------------------------- + dynamic_bitset & reset( size_type pos ); + + //! Resets all the bits in this bitset. + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- dynamic_bitset & reset(); - dynamic_bitset & flip( size_type n, size_type len ); - dynamic_bitset & flip( size_type n ); + + //! Toggles the bits in the range `[pos, pos + len)`. + //! + //! If `len` is zero, does nothing. Otherwise, toggles all the + //! bits in this bitset which have a position in `[pos, pos + + //! len - 1]`. + //! + //! \pre + //! `pos + len <= this->size()`. + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- + dynamic_bitset & flip( size_type pos, size_type len ); + + //! Toggles the bit at position `pos` in this bitset. + //! + //! \pre + //! `pos < this->size()`. + //! + //! \return + //! `*this`. + // ----------------------------------------------------------------------- + dynamic_bitset & flip( size_type pos ); + + //! Toggles the value of every bit in this bitset. + //! + //! \return + //! `*this`. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- dynamic_bitset & flip(); - reference at( size_type n ); + + //! A checked version of `operator[]()`. + //! + //! \return + //! The same as `operator[]( n )`. + //! + //! \par Throws + //! `std::out_of_range` if `pos` is not within the range of the + //! bitset. + // ----------------------------------------------------------------------- + reference at( size_type pos ); + + //! A checked version of `operator[]()`. + //! + //! \return + //! The same as `operator[]( n )`. + //! + //! \par Throws + //! `std::out_of_range` if `pos` is not within the range of the + //! bitset. + // ----------------------------------------------------------------------- bool at( size_type n ) const; - bool test( size_type n ) const; - bool test_set( size_type n, bool val = true ); + + //! Tests the bit at the given position. + //! + //! \pre + //! `pos < this->size()`. + //! + //! \return + //! `true` if bit `pos` is set, and `false` if it is zero. + // ----------------------------------------------------------------------- + bool test( size_type pos ) const; + + //! Sets bit `pos` if `val` is `true`, and clears it if `val` is + //! `false`. + //! + //! \pre + //! `pos < this->size()`. + //! + //! \return + //! The previous state of bit `pos`. + // ----------------------------------------------------------------------- + bool test_set( size_type pos, bool val = true ); + + //! Checks whether all bits in `*this` are set. + //! + //! \return + //! `true` if all bits in this bitset are set or if `size() == + //! 0`; otherwise `false`. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- bool all() const; + + //! Checks whether any bits in `*this` are set. + //! + //! \return + //! `true` if any bits in this bitset are set, otherwise + //! `false`. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- bool any() const; + + //! Checks whether this bitset has no set bit. + //! + //! \return + //! `true` if no bits in this bitset are set, otherwise `false`. + // ----------------------------------------------------------------------- bool none() const; + + //! Returns a copy of `*this` with all of its bits toggled. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + // ----------------------------------------------------------------------- dynamic_bitset operator~() const; + + //! Returns the number of bits in this bitset that are set. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- size_type count() const BOOST_NOEXCEPT; - // subscript + //! Returns a `reference` to the bit at position `pos`. + //! + //! \pre + //! `pos < this->size()`. + //! + //! \return + //! A `reference` to bit `pos`. Note that `reference` is a proxy + //! class with an assignment operator and a conversion to + //! `bool`, which allows you to use `operator[]` for assignment. + //! That is, you can write both `x = b[ n ]` and `b[ n ] = x`. + //! However, in many other respects the proxy is not the same as + //! the true reference type `bool &`. + // ----------------------------------------------------------------------- reference operator[]( size_type pos ); + + //! The same as `test( pos )`. + //! + //! \pre + //! `pos < this->size()`. + //! + //! \return + //! The same as `test( pos )`. + // ----------------------------------------------------------------------- bool operator[]( size_type pos ) const; + //! Returns the numeric value corresponding to the bits in + //! `*this`. + //! + //! \par Throws + //! `std::overflow_error` if that value is too large to be + //! represented in an `unsigned long`, i.e. if `*this` has any + //! non-zero bit at a position >= `std::numeric_limits< unsigned + //! long >::digits`. + // ----------------------------------------------------------------------- unsigned long to_ulong() const; + //! Returns the number of bits in this bitset. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- size_type size() const BOOST_NOEXCEPT; + + //! Returns the number of blocks in this bitset. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- size_type num_blocks() const BOOST_NOEXCEPT; + + //! Returns the maximum size of a bitset of this type. + //! + //! \return + //! The maximum size of a `dynamic_bitset` object having the + //! same type as `*this`. Note that if any `dynamic_bitset` + //! operation causes `size()` to exceed `max_size()` then + //! the behavior is undefined. + //! + //! [The semantics of this function could change slightly when + //! lib issue 197 will be closed.] + // ----------------------------------------------------------------------- size_type max_size() const BOOST_NOEXCEPT; + + //! Checks whether this bitset has size zero. + //! + //! \return + //! `this->size() == 0`. + //! + //! \par Note + //! Not to be confused with `none()`, which has different + //! semantics. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- bool empty() const BOOST_NOEXCEPT; + + //! Returns the total number of elements that `*this` can hold + //! without requiring reallocation. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- size_type capacity() const BOOST_NOEXCEPT; + + //! Informs the bitset of a planned change in size, so that it + //! can manage the storage allocation accordingly. After + //! `reserve()`, `capacity()` is greater or equal to the + //! argument of `reserve()` if reallocation happens; and equal + //! to the previous value of `capacity()` otherwise. + //! Reallocation happens at this point if and only if the + //! current capacity is less than the argument of `reserve()`. + //! + //! \par Note + //! It does not change the size of the bitset. + // ----------------------------------------------------------------------- void reserve( size_type num_bits ); + + //! Requests the bitset to reduce memory use by removing unused + //! capacity. + //! + //! \par Note + //! It does not change the size of the bitset. + //! + //! \par Throws + //! An allocation error if memory is exhausted (`std::bad_alloc` + //! if `Allocator` is a `std::allocator`). + // ----------------------------------------------------------------------- void shrink_to_fit(); - bool is_subset_of( const dynamic_bitset & a ) const; - bool is_proper_subset_of( const dynamic_bitset & a ) const; - bool intersects( const dynamic_bitset & a ) const; + //! Checks whether `*this` is a subset of `b`. + //! + //! \pre + //! `this->size() == b.size()`. + //! + //! \return + //! `true` if this bitset is a subset of bitset `b`. That is, it + //! returns `true` if, for every bit that is set in this bitset, + //! the corresponding bit in bitset `b` is also set. Otherwise + //! this function returns `false`. + // ----------------------------------------------------------------------- + bool is_subset_of( const dynamic_bitset & b ) const; - // lookup + //! Checks whether `*this` is a proper subset of `b`. + //! + //! \pre + //! `this->size() == b.size()`. + //! + //! \return + //! `true` if this bitset is a proper subset of bitset `b`. That + //! is, it returns `true` if, for every bit that is set in this + //! bitset, the corresponding bit in bitset a is also set and if + //! `this->count() < b.count()`. Otherwise this function returns + //! `false`. + // ----------------------------------------------------------------------- + bool is_proper_subset_of( const dynamic_bitset & b ) const; + + //! Checks whether `*this` intersects with `b`. + //! + //! \pre + //! `this->size() == b.size()`. + //! + //! \return + //! `true` if this bitset and `b` intersect. That is, it returns + //! `true` if, there is a bit which is set in this bitset, such + //! that the corresponding bit in bitset `b` is also set. + //! Otherwise this function returns `false`. + // ----------------------------------------------------------------------- + bool intersects( const dynamic_bitset & b ) const; + + //! Finds the first set bit in `*this`, if any. + //! + //! \return + //! The lowest index `i` such that bit `i` is set in `*this`, or + //! `npos` if `*this` has no bits set. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- size_type find_first() const; + + //! Finds the first set bit in `*this` with an index >= `pos`, + //! if any. + //! + //! \return + //! The lowest index `i` greater than or equal to `pos` such + //! that bit `i` is set in `*this`, or `npos` if no such index + //! exists. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- size_type find_first( size_type pos ) const; + + //! Finds the first bit set in `*this` with an index > `pos`, if + //! any. + //! + //! \return + //! The lowest index `i` greater than `pos` such that bit `i` is + //! set, or `npos` if no such index exists. + //! + //! \par Throws + //! Nothing. + // ----------------------------------------------------------------------- size_type find_next( size_type pos ) const; - // lexicographical comparison template< typename B, typename A > friend bool operator==( const dynamic_bitset< B, A > & a, const dynamic_bitset< B, A > & b ); @@ -229,7 +1032,8 @@ public: template< typename B, typename A > friend std::size_t hash_value( const dynamic_bitset< B, A > & a ); - // forward declaration for optional zero-copy serialization support + //! Optional zero-copy serialization support. + // ----------------------------------------------------------------------- class serialize_impl; friend class serialize_impl; @@ -335,62 +1139,275 @@ const typename dynamic_bitset< Block, Allocator >::block_width_type #endif -// Global Functions: +//! Compares two bitsets. +//! +//! \return +//! `true` if `a.size() == b.size()` and for all `i` in the range +//! `[0, a.size()]`, `a[ i ] == b[ i ]`. Otherwise `false`. +//! +//! \par Throws +//! Nothing. +//! +//! (Required by EqualityComparable.) +// ----------------------------------------------------------------------- +template< typename Block, typename Allocator > +bool operator==( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); -// comparison +//! Compares two bitsets. +//! +//! \return +//! `! ( a == b )`. +//! +//! \par Throws +//! Nothing. +// ----------------------------------------------------------------------- template< typename Block, typename Allocator > bool operator!=( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); +//! Compares two bitsets. +//! +//! \return +//! `true` if `a` is lexicographically less than `b`, otherwise +//! `false`. +//! +//! \par Throws +//! Nothing. +//! +//! (Required by LessThanComparable.) +// ----------------------------------------------------------------------- +template< typename Block, typename Allocator > +bool operator<( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); + +//! Compares two bitsets. +//! +//! \return +//! `a < b || a == b`. +//! +//! \par Throws +//! Nothing. +// ----------------------------------------------------------------------- template< typename Block, typename Allocator > bool operator<=( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); +//! Compares two bitsets. +//! +//! \return +//! `b < a`. +//! +//! \par Throws +//! Nothing. +// ----------------------------------------------------------------------- template< typename Block, typename Allocator > bool operator>( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); +//! Compares two bitsets. +//! +//! \return +//! `b <= a`. +//! +//! \par Throws +//! Nothing. +// ----------------------------------------------------------------------- template< typename Block, typename Allocator > bool operator>=( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); -// stream operators +//! Inserts a textual representation of `b` into the stream `os`, +//! highest bit first. Informally, the output is the same as: +//! +//! \code +//! std::basic_string s; +//! boost::to_string(x, s): +//! os << s; +//! \endcode +//! +//! except that the stream inserter takes into accout the locale +//! imbued into `os`, which `boost::to_string()` can't do. More +//! precisely: First, for each valid position `i` into the bitset b +//! let's put: `character_of( b[ i ) ] ) = b[ i ] ? os.widen( '1' ) +//! : os.widen( '0' );`. Let also `s` be a `std::basic_string` object, having length `b.size()` and such that, for +//! each `i` in `[0, b.size())`, `s[ i ]` is `character_of( b[ i ] +//! )`. Then, the output, the effects on `os` and the exception +//! behavior is the same as outputting the object `s` to `os` (same +//! width, same exception mask, same padding, same `setstate()` +//! logic.) +//! +//! \return +//! `os`. +// ----------------------------------------------------------------------- template< typename CharT, typename Traits, typename Block, typename Allocator > std::basic_ostream< CharT, Traits > & operator<<( std::basic_ostream< CharT, Traits > & os, const dynamic_bitset< Block, Allocator > & b ); +//! Extracts a `dynamic_bitset` from an input stream. +//! +//! \par Definitions +//! - A (non-eof) character `c` extracted from `is` is a bitset +//! digit if and only if either `Traits::eq(c, is.widen('0'))` +//! or `Traits::eq(c, is.widen('1'))` return `true`. +//! +//! - If `c` is a bitset digit, its corresponding bit value is 0 if +//! `Tr::eq(c, is.widen('0'))` returns true, 1 otherwise. +//! +//! The extractor begins by constructing a `sentry` object `k` as if +//! by `typename std::basic_istream< Char, Traits >::sentry k( is +//! )`. If `bool( k )` is `true`, it calls `b.clear()` then attempts +//! to extract characters from `is`. For each character `c` that is +//! a bitset digit, the corresponding bit value is appended to the +//! less significant end of `b` (appending may throw). If +//! `is.width()` is greater than zero and smaller than +//! `b.max_size()` then the maximum number `n` of bits appended is +//! `is.width()`; otherwise `n = b.max_size()`. Unless the extractor +//! is exited via an exception, characters are extracted (and +//! corresponding bits appended) until any of the following occurs: +//! +//! - `n` bits are stored into the bitset; +//! - end-of-file, or an error, occurs on the input sequence; +//! - the next available input character isn't a bitset digit. +//! +//! If no exception caused the function to exit then `is.width( 0 )` +//! is called, regardless of how many characters were actually +//! extracted. The sentry object `k` is destroyed. +//! +//! If the function extracts no characters, it calls `is.setstate( +//! std::ios::failbit )`, which may throw `std::ios_base::failure`. +//! +//! \return +//! `is`. +// ----------------------------------------------------------------------- template< typename CharT, typename Traits, typename Block, typename Allocator > std::basic_istream< CharT, Traits > & operator>>( std::basic_istream< CharT, Traits > & is, dynamic_bitset< Block, Allocator > & b ); -// bitset operations +//! Performs a bitwise-AND of two bitsets. +//! +//! \pre +//! `a.size() == b.size()`. +//! +//! \return +//! A new bitset which is the bitwise-AND of the bitsets `a` and +//! `b`. +//! +//! \par Throws +//! An allocation error if memory is exhausted (`std::bad_alloc` if +//! `Allocator` is a `std::allocator`). +// ----------------------------------------------------------------------- template< typename Block, typename Allocator > dynamic_bitset< Block, Allocator > -operator&( const dynamic_bitset< Block, Allocator > & b1, const dynamic_bitset< Block, Allocator > & b2 ); +operator&( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); +//! Performs a bitwise-OR of two bitsets. +//! +//! \pre +//! `a.size() == b.size()`. +//! +//! \return +//! A new bitset which is the bitwise-OR of the bitsets `a` and `b`. +//! +//! \par Throws +//! An allocation error if memory is exhausted (`std::bad_alloc` if +//! `Allocator` is a `std::allocator`). +// ----------------------------------------------------------------------- template< typename Block, typename Allocator > dynamic_bitset< Block, Allocator > -operator|( const dynamic_bitset< Block, Allocator > & b1, const dynamic_bitset< Block, Allocator > & b2 ); +operator|( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); +//! Performs a bitwise-XOR of two bitsets. +//! +//! \pre +//! `a.size() == b.size()`. +//! +//! \return +//! A new bitset which is the bitwise-XOR of the bitsets `a` and +//! `b`. +//! +//! \par Throws +//! An allocation error if memory is exhausted (`std::bad_alloc` if +//! `Allocator` is a `std::allocator`). +// ----------------------------------------------------------------------- template< typename Block, typename Allocator > dynamic_bitset< Block, Allocator > -operator^( const dynamic_bitset< Block, Allocator > & b1, const dynamic_bitset< Block, Allocator > & b2 ); +operator^( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); +//! Calculates the set difference of two bitsets. +//! +//! \pre +//! `a.size() == b.size()`. +//! +//! \return +//! A new bitset which is the set difference of the bitsets `a` and +//! `b`. +//! +//! \par Throws +//! An allocation error if memory is exhausted (`std::bad_alloc` if +//! `Allocator` is a `std::allocator`). +// ----------------------------------------------------------------------- template< typename Block, typename Allocator > dynamic_bitset< Block, Allocator > -operator-( const dynamic_bitset< Block, Allocator > & b1, const dynamic_bitset< Block, Allocator > & b2 ); +operator-( const dynamic_bitset< Block, Allocator > & a, const dynamic_bitset< Block, Allocator > & b ); -// namespace scope swap +//! Exchanges the contents of `a` and `b`. +//! +//! \par Throws +//! Nothing. +// ----------------------------------------------------------------------- template< typename Block, typename Allocator > -void swap( dynamic_bitset< Block, Allocator > & b1, dynamic_bitset< Block, Allocator > & b2 ) BOOST_NOEXCEPT; +void swap( dynamic_bitset< Block, Allocator > & a, dynamic_bitset< Block, Allocator > & b ) BOOST_NOEXCEPT; +//! Copies a representation of `b` into the string `s`. Character +//! position `i` in the string corresponds to bit position `b.size() +//! - 1 - i`. +//! +//! \par Throws +//! An allocation error from `s` if memory is exhausted. +//! +//! \par Rationale +//! This function is not a member function taking zero arguments and +//! returning a string for a couple of historical reasons. First, this +//! version could be slighly more efficient because the string is not +//! copied. Second, as a member function, to allow for flexibility with +//! regards to the template parameters of `basic_string`, the member +//! function would require explicit template parameters. Few C++ programmers +//! were familiar with explicit template parameters, and some C++ compilers +//! did not handle them properly. +// ----------------------------------------------------------------------- template< typename Block, typename Allocator, typename stringT > void to_string( const dynamic_bitset< Block, Allocator > & b, stringT & s ); +//! Writes the bits of the bitset into the iterator `result`, a +//! block at a time. +//! +//! The first block written represents the bits in the position +//! range `[0, bits_per_block)` in the bitset, the second block +//! written the bits in the range `[bits_per_block, +//! 2*bits_per_block)`, and so on. For each block `bval` written, +//! the bit `( bval >> i ) & 1` corresponds to the bit at position +//! `b * bits_per_block + i` in the bitset. +//! +//! \pre +//! The type `BlockOutputIterator` must be a model of +//! LegacyOutputIterator +//! and its `value_type` must be the same type as `Block`. +//! Furthermore, the size of the output range must be greater than +//! or equal to `b.num_blocks()`. +// ----------------------------------------------------------------------- template< typename Block, typename Allocator, typename BlockOutputIterator > void to_block_range( const dynamic_bitset< Block, Allocator > & b, BlockOutputIterator result ); -template< typename BlockIterator, typename B, typename A > +//! Reads blocks from the iterator range into the bitset. +//! +//! \pre +//! The type `BlockIterator` must be a model of +//! LegacyInputIterator +//! and its `value_type` must be the same type as `Block`. The size +//! of the iterator range must be less than or equal to +//! `b.num_blocks()`. +// ----------------------------------------------------------------------- +template< typename BlockIterator, typename Block, typename Allocator > inline void -from_block_range( BlockIterator first, BlockIterator last, dynamic_bitset< B, A > & result ); +from_block_range( BlockIterator first, BlockIterator last, dynamic_bitset< Block, Allocator > & result ); } diff --git a/include/boost/dynamic_bitset/impl/dynamic_bitset.tpp b/include/boost/dynamic_bitset/impl/dynamic_bitset.tpp index 389dfb1..8aaeca7 100644 --- a/include/boost/dynamic_bitset/impl/dynamic_bitset.tpp +++ b/include/boost/dynamic_bitset/impl/dynamic_bitset.tpp @@ -176,16 +176,6 @@ dynamic_bitset< Block, Allocator >::dynamic_bitset( init_from_string( s, pos, n, num_bits ); } -template< typename Block, typename Allocator > -template< typename CharT, typename Traits, typename Alloc > -dynamic_bitset< Block, Allocator >::dynamic_bitset( - const std::basic_string< CharT, Traits, Alloc > & s, - typename std::basic_string< CharT, Traits, Alloc >::size_type pos ) - : m_bits( Allocator() ), m_num_bits( 0 ) -{ - init_from_string( s, pos, ( std::basic_string< CharT, Traits, Alloc >::npos ), npos ); -} - template< typename Block, typename Allocator > template< typename BlockInputIterator > dynamic_bitset< Block, Allocator >::dynamic_bitset(