@@ -59,9 +59,10 @@ namespace sparrow
5959
6060 using base_type = dynamic_bitset_base<buffer<T>>; // /< Base class type
6161 using storage_type = typename base_type::storage_type; // /< Underlying storage container type
62- using block_type = typename base_type::block_type; // /< Type of each storage block (same as T)
63- using value_type = typename base_type::value_type; // /< Type of individual bit values (bool)
64- using size_type = typename base_type::size_type; // /< Type used for sizes and indices
62+ using default_allocator = typename storage_type::default_allocator; // /< Type of default allocator
63+ using block_type = typename base_type::block_type; // /< Type of each storage block (same as T)
64+ using value_type = typename base_type::value_type; // /< Type of individual bit values (bool)
65+ using size_type = typename base_type::size_type; // /< Type used for sizes and indices
6566
6667 /* *
6768 * @brief Constructs a dynamic_bitset from an input range of convertible values.
@@ -71,7 +72,9 @@ namespace sparrow
7172 * values result in set bits (1), while zero/false values result in unset bits (0).
7273 *
7374 * @tparam R Input range type that must satisfy std::ranges::input_range
75+ * @tparam A Allocator type that must satisfy sparrow::allocator
7476 * @param r The input range whose elements will be converted to bits
77+ * @param a The allocator used internally
7578 *
7679 * @pre The range elements must be convertible to value_type (bool)
7780 * @pre The range must have a computable size via std::ranges::size
@@ -82,10 +85,10 @@ namespace sparrow
8285 * dynamic_bitset<std::uint8_t> bits(values); // Results in: 10101
8386 * @endcode
8487 */
85- template <std::ranges::input_range R>
88+ template <std::ranges::input_range R, allocator A = default_allocator >
8689 requires std::convertible_to<std::ranges::range_value_t <R>, value_type>
87- constexpr explicit dynamic_bitset (const R& r)
88- : dynamic_bitset(std::ranges::size(r), true)
90+ constexpr explicit dynamic_bitset (const R& r, const A& a = A() )
91+ : dynamic_bitset(std::ranges::size(r), true, a )
8992 {
9093 std::size_t i = 0 ;
9194 for (auto value : r)
@@ -104,7 +107,9 @@ namespace sparrow
104107 * Constructs a bitset with zero bits. The bitset can later be resized
105108 * or bits can be added using the provided methods.
106109 */
107- constexpr dynamic_bitset ();
110+ template <class A = default_allocator>
111+ requires (not std::same_as<A, dynamic_bitset<T>> and allocator<A>)
112+ constexpr dynamic_bitset (const A& a = A());
108113
109114 /* *
110115 * @brief Constructs a bitset with n bits, all initialized to false.
@@ -114,7 +119,8 @@ namespace sparrow
114119 * @post size() == n
115120 * @post All bits are set to false
116121 */
117- constexpr explicit dynamic_bitset (size_type n);
122+ template <allocator A = default_allocator>
123+ constexpr explicit dynamic_bitset (size_type n, const A& a = A());
118124
119125 /* *
120126 * @brief Constructs a bitset with n bits, all initialized to the specified value.
@@ -125,7 +131,8 @@ namespace sparrow
125131 * @post size() == n
126132 * @post All bits are set to v
127133 */
128- constexpr dynamic_bitset (size_type n, value_type v);
134+ template <allocator A = default_allocator>
135+ constexpr dynamic_bitset (size_type n, value_type v, const A& a = A());
129136
130137 /* *
131138 * @brief Constructs a bitset using existing memory.
@@ -142,7 +149,8 @@ namespace sparrow
142149 * @warning The caller must ensure the memory pointed to by p remains valid
143150 * and contains properly formatted bit data.
144151 */
145- constexpr dynamic_bitset (block_type* p, size_type n);
152+ template <allocator A = default_allocator>
153+ constexpr dynamic_bitset (block_type* p, size_type n, const A& a = A());
146154
147155 /* *
148156 * @brief Constructs a bitset using existing memory with null count tracking.
@@ -159,12 +167,19 @@ namespace sparrow
159167 * @post size() == n
160168 * @post null_count() == null_count
161169 */
162- constexpr dynamic_bitset (block_type* p, size_type n, size_type null_count);
170+ template <allocator A = default_allocator>
171+ constexpr dynamic_bitset (block_type* p, size_type n, size_type null_count, const A& a = A());
163172
164173 constexpr ~dynamic_bitset () = default ;
165174 constexpr dynamic_bitset (const dynamic_bitset&) = default;
166175 constexpr dynamic_bitset (dynamic_bitset&&) noexcept = default;
167176
177+ template <allocator A>
178+ constexpr dynamic_bitset (const dynamic_bitset& rhs, const A& a);
179+
180+ template <allocator A>
181+ constexpr dynamic_bitset (dynamic_bitset&& rhs, const A& a);
182+
168183 constexpr dynamic_bitset& operator =(const dynamic_bitset&) = default ;
169184 constexpr dynamic_bitset& operator =(dynamic_bitset&&) noexcept = default ;
170185
@@ -179,23 +194,27 @@ namespace sparrow
179194 };
180195
181196 template <std::integral T>
182- constexpr dynamic_bitset<T>::dynamic_bitset()
183- : base_type(storage_type(), 0u )
197+ template <class A >
198+ requires (not std::same_as<A, dynamic_bitset<T>> and allocator<A>)
199+ constexpr dynamic_bitset<T>::dynamic_bitset(const A& a)
200+ : base_type(storage_type(a), 0u )
184201 {
185202 base_type::zero_unused_bits ();
186203 }
187204
188205 template <std::integral T>
189- constexpr dynamic_bitset<T>::dynamic_bitset(size_type n)
190- : dynamic_bitset(n, false )
206+ template <allocator A>
207+ constexpr dynamic_bitset<T>::dynamic_bitset(size_type n, const A& a)
208+ : dynamic_bitset(n, false , a)
191209 {
192210 base_type::zero_unused_bits ();
193211 }
194212
195213 template <std::integral T>
196- constexpr dynamic_bitset<T>::dynamic_bitset(size_type n, value_type value)
214+ template <allocator A>
215+ constexpr dynamic_bitset<T>::dynamic_bitset(size_type n, value_type value, const A& a)
197216 : base_type(
198- storage_type (this ->compute_block_count (n), value ? block_type(~block_type (0 )) : block_type(0 )),
217+ storage_type (this ->compute_block_count (n), value ? block_type(~block_type (0 )) : block_type(0 ), a ),
199218 n,
200219 value ? 0u : n
201220 )
@@ -204,20 +223,36 @@ namespace sparrow
204223 }
205224
206225 template <std::integral T>
207- constexpr dynamic_bitset<T>::dynamic_bitset(block_type* p, size_type n)
208- : base_type(storage_type(p, p != nullptr ? this ->compute_block_count (n) : 0), n)
226+ template <allocator A>
227+ constexpr dynamic_bitset<T>::dynamic_bitset(block_type* p, size_type n, const A& a)
228+ : base_type(storage_type(p, p != nullptr ? this ->compute_block_count (n) : 0, a), n)
209229 {
210230 base_type::zero_unused_bits ();
211231 }
212232
213233 template <std::integral T>
214- constexpr dynamic_bitset<T>::dynamic_bitset(block_type* p, size_type n, size_type null_count)
215- : base_type(storage_type(p, this ->compute_block_count (n)), n, null_count)
234+ template <allocator A>
235+ constexpr dynamic_bitset<T>::dynamic_bitset(block_type* p, size_type n, size_type null_count, const A& a)
236+ : base_type(storage_type(p, this ->compute_block_count (n), a), n, null_count)
216237 {
217238 base_type::zero_unused_bits ();
218239 SPARROW_ASSERT_TRUE (base_type::null_count () == base_type::size () - base_type::count_non_null ());
219240 }
220241
242+ template <std::integral T>
243+ template <allocator A>
244+ constexpr dynamic_bitset<T>::dynamic_bitset(const dynamic_bitset& rhs, const A& a)
245+ : base_type(storage_type(rhs, a))
246+ {
247+ }
248+
249+ template <std::integral T>
250+ template <allocator A>
251+ constexpr dynamic_bitset<T>::dynamic_bitset(dynamic_bitset&& rhs, const A& a)
252+ : base_type(storage_type(std::move(rhs), a))
253+ {
254+ }
255+
221256 /* *
222257 * @brief Type alias for a validity bitmap using 8-bit storage blocks.
223258 *
0 commit comments