@@ -74,6 +74,14 @@ concept LegalDataConversion =
74
74
std::is_convertible_v<std::remove_reference_t <From> (*)[],
75
75
std::remove_reference_t <To> (*)[]>;
76
76
77
+ // Akin to `std::constructible_from<span, T>`, but meant to be used in a
78
+ // type-deducing context where we don't know what args would be deduced;
79
+ // `std::constructible_from` can't be directly used in such a case since the
80
+ // type parameters must be fully-specified (e.g. `span<int>`), requiring us to
81
+ // have that knowledge already.
82
+ template <typename T>
83
+ concept SpanConstructibleFrom = requires(const T& t) { span (t); };
84
+
77
85
template <typename T, typename It>
78
86
concept CompatibleIter = std::contiguous_iterator<It> &&
79
87
LegalDataConversion<std::iter_reference_t <It>, T>;
@@ -1488,42 +1496,20 @@ auto as_writable_chars(span<T, X, InternalPtrType> s) noexcept {
1488
1496
span<char , N>(reinterpret_cast <char *>(s.data ()), s.size_bytes ()));
1489
1497
}
1490
1498
1491
- // Type-deducing helper for constructing a span.
1492
- //
1493
- // # Safety
1494
- // The contiguous iterator `it` must point to the first element of at least
1495
- // `size` many elements or Undefined Behaviour may result as the span may give
1496
- // access beyond the bounds of the collection pointed to by `it`.
1497
- template <int &... ExplicitArgumentBarrier, typename It>
1498
- UNSAFE_BUFFER_USAGE constexpr auto make_span (
1499
- It it,
1500
- StrictNumeric<size_t > size) noexcept {
1501
- using T = std::remove_reference_t <std::iter_reference_t <It>>;
1502
- // SAFETY: The caller guarantees that `it` is the first of at least `size`
1503
- // many elements.
1504
- return UNSAFE_BUFFERS (span<T>(it, size));
1505
- }
1506
-
1507
1499
// Type-deducing helper for constructing a span.
1508
1500
// Deprecated: Use CTAD (i.e. use `span()` directly without template arguments).
1509
1501
// TODO(crbug.com/341907909): Remove.
1510
1502
//
1511
- // # Checks
1512
- // The function CHECKs that `it <= end` and will terminate otherwise.
1513
- //
1514
- // # Safety
1515
- // The contiguous iterator `it` and its end sentinel `end` must be for the same
1516
- // allocation or Undefined Behaviour may result as the span may give access
1517
- // beyond the bounds of the collection pointed to by `it`.
1518
- template <int &... ExplicitArgumentBarrier,
1519
- typename It,
1520
- typename End,
1521
- typename = std::enable_if_t <!std::is_convertible_v<End, size_t >>>
1522
- UNSAFE_BUFFER_USAGE constexpr auto make_span (It it, End end) noexcept {
1523
- using T = std::remove_reference_t <std::iter_reference_t <It>>;
1524
- // SAFETY: The caller guarantees that `it` and `end` are iterators of the
1525
- // same allocation.
1526
- return UNSAFE_BUFFERS (span<T>(it, end));
1503
+ // SAFETY: `it` must point to the first of a (possibly-empty) series of
1504
+ // contiguous valid elements. If `end_or_size` is a size, the series must
1505
+ // contain at least that many valid elements; if it is an iterator or sentinel,
1506
+ // it must refer to the same allocation, and all elements in the range [it,
1507
+ // end_or_size) must be valid. Otherwise, the span will allow access to invalid
1508
+ // elements, resulting in UB.
1509
+ template <int &... ExplicitArgumentBarrier, typename It, typename EndOrSize>
1510
+ requires (std::contiguous_iterator<It>)
1511
+ UNSAFE_BUFFER_USAGE constexpr auto make_span(It it, EndOrSize end_or_size) {
1512
+ return UNSAFE_BUFFERS (span (it, end_or_size));
1527
1513
}
1528
1514
1529
1515
// make_span utility function that deduces both the span's value_type and extent
@@ -1533,6 +1519,7 @@ UNSAFE_BUFFER_USAGE constexpr auto make_span(It it, End end) noexcept {
1533
1519
// Deprecated: Use CTAD (i.e. use `span()` directly without template arguments).
1534
1520
// TODO(crbug.com/341907909): Remove.
1535
1521
template <int &... ExplicitArgumentBarrier, typename Container>
1522
+ requires (internal::SpanConstructibleFrom<Container>)
1536
1523
constexpr auto make_span(Container&& container) noexcept {
1537
1524
return span (std::forward<Container>(container));
1538
1525
}
@@ -1664,9 +1651,9 @@ constexpr span<const uint8_t, N> byte_span_with_nul_from_cstring(
1664
1651
// or vector-like objects holding other scalar types, prior to passing them
1665
1652
// into an API that requires byte spans.
1666
1653
template <int &... ExplicitArgumentBarrier, typename Spannable>
1667
- requires requires ( const Spannable& arg) { make_span (arg); }
1654
+ requires (internal::SpanConstructibleFrom< Spannable>)
1668
1655
constexpr auto as_byte_span(const Spannable& arg) {
1669
- return as_bytes (make_span (arg));
1656
+ return as_bytes (span (arg));
1670
1657
}
1671
1658
1672
1659
template <int &... ExplicitArgumentBarrier, typename T, size_t N>
@@ -1681,26 +1668,20 @@ constexpr span<const uint8_t, N * sizeof(T)> as_byte_span(
1681
1668
// or vector-like objects holding other scalar types, prior to passing them
1682
1669
// into an API that requires mutable byte spans.
1683
1670
template <int &... ExplicitArgumentBarrier, typename Spannable>
1684
- requires requires (Spannable&& arg) {
1685
- make_span (arg);
1686
- requires !std::is_const_v<typename decltype (make_span (arg))::element_type>;
1687
- }
1671
+ requires (internal::SpanConstructibleFrom<Spannable> &&
1672
+ !std::is_const_v<typename decltype (span(
1673
+ std::declval<Spannable>()))::element_type>)
1688
1674
constexpr auto as_writable_byte_span(Spannable&& arg) {
1689
- return as_writable_bytes (make_span (std::forward<Spannable>(arg)));
1675
+ return as_writable_bytes (span (std::forward<Spannable>(arg)));
1690
1676
}
1691
1677
1692
1678
// This overload for arrays preserves the compile-time size N of the array in
1693
1679
// the span type signature span<uint8_t, N>.
1694
1680
template <int &... ExplicitArgumentBarrier, typename T, size_t N>
1681
+ requires (!std::is_const_v<T>)
1695
1682
constexpr span<uint8_t, N * sizeof(T)> as_writable_byte_span(
1696
1683
T (&arr LIFETIME_BOUND)[N]) {
1697
- return as_writable_bytes (make_span (arr));
1698
- }
1699
-
1700
- template <int &... ExplicitArgumentBarrier, typename T, size_t N>
1701
- constexpr span<uint8_t , N * sizeof (T)> as_writable_byte_span(
1702
- T (&&arr LIFETIME_BOUND)[N]) {
1703
- return as_writable_bytes (make_span (arr));
1684
+ return as_writable_bytes (span (arr));
1704
1685
}
1705
1686
1706
1687
namespace internal {
0 commit comments