Skip to content

Commit 2f7997c

Browse files
committed
fix(buffers): make_buffer returns mutable_buffer for by-value mutable ranges
The generic mutable overload took an lvalue reference `make_buffer(T&)`, so a `boost::span<char>` passed as a temporary could not bind to it and fell through to the const overload, returning a `const_buffer` (#147). `std::span<char>` only escaped this via a dedicated by-value overload. Change the generic mutable overloads to a forwarding reference `make_buffer(T&&)` so by-value mutable contiguous ranges bind there and return `mutable_buffer`. Remove the now-redundant explicit C-array, std::array, std::vector, std::basic_string, and std::span overloads, which the concept-based generic overloads fully subsume; prune the includes they required. Behavior is preserved for all non-empty inputs; for empty array/ const-string/span the returned (size-0) buffer's data pointer is now normalized to nullptr, matching vector/string. Add a prvalue std::span regression test plus a boost::span test guarded by __has_include so Capy still builds and passes without Boost present.
1 parent 4b27cdd commit 2f7997c

12 files changed

Lines changed: 181 additions & 297 deletions

File tree

doc/modules/ROOT/pages/5.buffers/5b.types.adoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,16 @@ auto buf = make_buffer(str);
140140
// From std::string_view
141141
std::string_view sv = "hello";
142142
auto buf = make_buffer(sv);
143+
144+
// From a span (std::span or boost::span)
145+
std::span<char> sp(arr);
146+
auto buf = make_buffer(sp);
143147
----
144148

149+
`make_buffer` accepts any sized, contiguous range of trivially-copyable
150+
elements—including `std::span` and `boost::span`—in addition to the
151+
sources shown above.
152+
145153
The returned buffer type depends on constness:
146154

147155
* Non-const containers → `mutable_buffer`

include/boost/capy/buffers/make_buffer.hpp

Lines changed: 14 additions & 294 deletions
Original file line numberDiff line numberDiff line change
@@ -124,242 +124,6 @@ make_buffer(
124124
size < max_size ? size : max_size);
125125
}
126126

127-
/** Return a buffer from a C-style array.
128-
*/
129-
template<class T, std::size_t N>
130-
requires std::is_trivially_copyable_v<T>
131-
[[nodiscard]]
132-
mutable_buffer
133-
make_buffer(
134-
T (&data)[N]) noexcept
135-
{
136-
return mutable_buffer(
137-
data, N * sizeof(T));
138-
}
139-
140-
/** Return a buffer from a C-style array with a maximum size.
141-
*/
142-
template<class T, std::size_t N>
143-
requires std::is_trivially_copyable_v<T>
144-
[[nodiscard]]
145-
mutable_buffer
146-
make_buffer(
147-
T (&data)[N],
148-
std::size_t max_size) noexcept
149-
{
150-
return mutable_buffer(
151-
data,
152-
N * sizeof(T) < max_size ? N * sizeof(T) : max_size);
153-
}
154-
155-
/** Return a buffer from a const C-style array.
156-
*/
157-
template<class T, std::size_t N>
158-
requires std::is_trivially_copyable_v<T>
159-
[[nodiscard]]
160-
const_buffer
161-
make_buffer(
162-
T const (&data)[N]) noexcept
163-
{
164-
return const_buffer(
165-
data, N * sizeof(T));
166-
}
167-
168-
/** Return a buffer from a const C-style array with a maximum size.
169-
*/
170-
template<class T, std::size_t N>
171-
requires std::is_trivially_copyable_v<T>
172-
[[nodiscard]]
173-
const_buffer
174-
make_buffer(
175-
T const (&data)[N],
176-
std::size_t max_size) noexcept
177-
{
178-
return const_buffer(
179-
data,
180-
N * sizeof(T) < max_size ? N * sizeof(T) : max_size);
181-
}
182-
183-
// std::array
184-
185-
/** Return a buffer from a std::array.
186-
*/
187-
template<class T, std::size_t N>
188-
requires std::is_trivially_copyable_v<T>
189-
[[nodiscard]]
190-
mutable_buffer
191-
make_buffer(
192-
std::array<T, N>& data) noexcept
193-
{
194-
return mutable_buffer(
195-
data.data(), data.size() * sizeof(T));
196-
}
197-
198-
/** Return a buffer from a std::array with a maximum size.
199-
*/
200-
template<class T, std::size_t N>
201-
requires std::is_trivially_copyable_v<T>
202-
[[nodiscard]]
203-
mutable_buffer
204-
make_buffer(
205-
std::array<T, N>& data,
206-
std::size_t max_size) noexcept
207-
{
208-
return mutable_buffer(
209-
data.data(),
210-
data.size() * sizeof(T) < max_size
211-
? data.size() * sizeof(T) : max_size);
212-
}
213-
214-
/** Return a buffer from a const std::array.
215-
*/
216-
template<class T, std::size_t N>
217-
requires std::is_trivially_copyable_v<T>
218-
[[nodiscard]]
219-
const_buffer
220-
make_buffer(
221-
std::array<T, N> const& data) noexcept
222-
{
223-
return const_buffer(
224-
data.data(), data.size() * sizeof(T));
225-
}
226-
227-
/** Return a buffer from a const std::array with a maximum size.
228-
*/
229-
template<class T, std::size_t N>
230-
requires std::is_trivially_copyable_v<T>
231-
[[nodiscard]]
232-
const_buffer
233-
make_buffer(
234-
std::array<T, N> const& data,
235-
std::size_t max_size) noexcept
236-
{
237-
return const_buffer(
238-
data.data(),
239-
data.size() * sizeof(T) < max_size
240-
? data.size() * sizeof(T) : max_size);
241-
}
242-
243-
// std::vector
244-
245-
/** Return a buffer from a std::vector.
246-
*/
247-
template<class T, class Allocator>
248-
requires std::is_trivially_copyable_v<T>
249-
[[nodiscard]]
250-
mutable_buffer
251-
make_buffer(
252-
std::vector<T, Allocator>& data) noexcept
253-
{
254-
return mutable_buffer(
255-
data.size() ? data.data() : nullptr,
256-
data.size() * sizeof(T));
257-
}
258-
259-
/** Return a buffer from a std::vector with a maximum size.
260-
*/
261-
template<class T, class Allocator>
262-
requires std::is_trivially_copyable_v<T>
263-
[[nodiscard]]
264-
mutable_buffer
265-
make_buffer(
266-
std::vector<T, Allocator>& data,
267-
std::size_t max_size) noexcept
268-
{
269-
return mutable_buffer(
270-
data.size() ? data.data() : nullptr,
271-
data.size() * sizeof(T) < max_size
272-
? data.size() * sizeof(T) : max_size);
273-
}
274-
275-
/** Return a buffer from a const std::vector.
276-
*/
277-
template<class T, class Allocator>
278-
requires std::is_trivially_copyable_v<T>
279-
[[nodiscard]]
280-
const_buffer
281-
make_buffer(
282-
std::vector<T, Allocator> const& data) noexcept
283-
{
284-
return const_buffer(
285-
data.size() ? data.data() : nullptr,
286-
data.size() * sizeof(T));
287-
}
288-
289-
/** Return a buffer from a const std::vector with a maximum size.
290-
*/
291-
template<class T, class Allocator>
292-
requires std::is_trivially_copyable_v<T>
293-
[[nodiscard]]
294-
const_buffer
295-
make_buffer(
296-
std::vector<T, Allocator> const& data,
297-
std::size_t max_size) noexcept
298-
{
299-
return const_buffer(
300-
data.size() ? data.data() : nullptr,
301-
data.size() * sizeof(T) < max_size
302-
? data.size() * sizeof(T) : max_size);
303-
}
304-
305-
// std::basic_string
306-
307-
/** Return a buffer from a std::basic_string.
308-
*/
309-
template<class CharT, class Traits, class Allocator>
310-
[[nodiscard]]
311-
mutable_buffer
312-
make_buffer(
313-
std::basic_string<CharT, Traits, Allocator>& data) noexcept
314-
{
315-
return mutable_buffer(
316-
data.size() ? &data[0] : nullptr,
317-
data.size() * sizeof(CharT));
318-
}
319-
320-
/** Return a buffer from a std::basic_string with a maximum size.
321-
*/
322-
template<class CharT, class Traits, class Allocator>
323-
[[nodiscard]]
324-
mutable_buffer
325-
make_buffer(
326-
std::basic_string<CharT, Traits, Allocator>& data,
327-
std::size_t max_size) noexcept
328-
{
329-
return mutable_buffer(
330-
data.size() ? &data[0] : nullptr,
331-
data.size() * sizeof(CharT) < max_size
332-
? data.size() * sizeof(CharT) : max_size);
333-
}
334-
335-
/** Return a buffer from a const std::basic_string.
336-
*/
337-
template<class CharT, class Traits, class Allocator>
338-
[[nodiscard]]
339-
const_buffer
340-
make_buffer(
341-
std::basic_string<CharT, Traits, Allocator> const& data) noexcept
342-
{
343-
return const_buffer(
344-
data.data(),
345-
data.size() * sizeof(CharT));
346-
}
347-
348-
/** Return a buffer from a const std::basic_string with a maximum size.
349-
*/
350-
template<class CharT, class Traits, class Allocator>
351-
[[nodiscard]]
352-
const_buffer
353-
make_buffer(
354-
std::basic_string<CharT, Traits, Allocator> const& data,
355-
std::size_t max_size) noexcept
356-
{
357-
return const_buffer(
358-
data.data(),
359-
data.size() * sizeof(CharT) < max_size
360-
? data.size() * sizeof(CharT) : max_size);
361-
}
362-
363127
// std::basic_string_view
364128

365129
/** Return a buffer from a std::basic_string_view.
@@ -390,62 +154,6 @@ make_buffer(
390154
? data.size() * sizeof(CharT) : max_size);
391155
}
392156

393-
// std::span
394-
395-
/** Return a buffer from a mutable std::span.
396-
*/
397-
template<class T, std::size_t Extent>
398-
requires (!std::is_const_v<T> && sizeof(T) == 1)
399-
[[nodiscard]]
400-
mutable_buffer
401-
make_buffer(
402-
std::span<T, Extent> data) noexcept
403-
{
404-
return mutable_buffer(data.data(), data.size());
405-
}
406-
407-
/** Return a buffer from a mutable std::span with a maximum size.
408-
*/
409-
template<class T, std::size_t Extent>
410-
requires (!std::is_const_v<T> && sizeof(T) == 1)
411-
[[nodiscard]]
412-
mutable_buffer
413-
make_buffer(
414-
std::span<T, Extent> data,
415-
std::size_t max_size) noexcept
416-
{
417-
return mutable_buffer(
418-
data.data(),
419-
data.size() < max_size ? data.size() : max_size);
420-
}
421-
422-
/** Return a buffer from a const std::span.
423-
*/
424-
template<class T, std::size_t Extent>
425-
requires (sizeof(T) == 1)
426-
[[nodiscard]]
427-
const_buffer
428-
make_buffer(
429-
std::span<T const, Extent> data) noexcept
430-
{
431-
return const_buffer(data.data(), data.size());
432-
}
433-
434-
/** Return a buffer from a const std::span with a maximum size.
435-
*/
436-
template<class T, std::size_t Extent>
437-
requires (sizeof(T) == 1)
438-
[[nodiscard]]
439-
const_buffer
440-
make_buffer(
441-
std::span<T const, Extent> data,
442-
std::size_t max_size) noexcept
443-
{
444-
return const_buffer(
445-
data.data(),
446-
data.size() < max_size ? data.size() : max_size);
447-
}
448-
449157
// Contiguous ranges
450158

451159
namespace detail {
@@ -473,11 +181,17 @@ concept const_contiguous_range =
473181
} // detail
474182

475183
/** Return a buffer from a mutable contiguous range.
184+
185+
Accepts any sized, contiguous range of trivially-copyable,
186+
non-const elements, including `std::vector`, `std::array`,
187+
`std::string`, `std::span`, `boost::span`, and built-in arrays,
188+
whether passed as an lvalue or a temporary. The returned buffer
189+
refers to the range's storage, which must outlive the buffer.
476190
*/
477191
template<detail::mutable_contiguous_range T>
478192
[[nodiscard]]
479193
mutable_buffer
480-
make_buffer(T& data) noexcept
194+
make_buffer(T&& data) noexcept
481195
{
482196
return mutable_buffer(
483197
std::ranges::size(data) ? std::ranges::data(data) : nullptr,
@@ -490,7 +204,7 @@ template<detail::mutable_contiguous_range T>
490204
[[nodiscard]]
491205
mutable_buffer
492206
make_buffer(
493-
T& data,
207+
T&& data,
494208
std::size_t max_size) noexcept
495209
{
496210
auto const n = std::ranges::size(data) * sizeof(std::ranges::range_value_t<T>);
@@ -500,6 +214,12 @@ make_buffer(
500214
}
501215

502216
/** Return a buffer from a const contiguous range.
217+
218+
Accepts any sized, contiguous range of trivially-copyable
219+
elements with const access, including const `std::vector`,
220+
`std::array`, `std::string`, `std::span`, `boost::span`, and
221+
string literals. The returned buffer refers to the range's
222+
storage, which must outlive the buffer.
503223
*/
504224
template<detail::non_buffer_contiguous_range T>
505225
[[nodiscard]]

include/boost/capy/test/buffer_source.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <boost/capy/test/fuse.hpp>
2121

2222
#include <algorithm>
23+
#include <span>
2324
#include <string>
2425
#include <string_view>
2526

test/unit/buffers/buffer_param.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "test_buffers.hpp"
1414

1515
#include <cstring>
16+
#include <span>
1617
#include <string>
1718
#include <vector>
1819

0 commit comments

Comments
 (0)