This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++20 status.

### 3101. `span`'s `Container` constructors need another constraint

Section: 22.7.3.2 [span.cons] Status: C++20 Submitter: Stephan T. Lavavej Opened: 2018-04-12 Last modified: 2021-02-25

Priority: 1

View all other issues in [span.cons].

View all issues with C++20 status.

Discussion:

When I overhauled `span`'s constructor constraints, I was careful about the built-in array, `std::array`, and converting `span` constructors. These types contain bounds information, so we can achieve safety at compile-time by permitting implicit conversions if and only if the destination extent is dynamic (this accepts anything by recording the size at runtime) or the source and destination extents are identical. However, I missed the fact that the `Container` constructors are the opposite case. A `Container` (e.g. a `vector`) has a size that's known only at runtime. It's safe to convert this to a `span` with `dynamic_extent`, but for consistency and safety, this shouldn't implicitly convert to a `span` with fixed extent. (The more verbose `(ptr, count)` and `(first, last)` constructors are available to construct fixed extent spans from runtime-length ranges. Note that debug precondition checks are equally possible with the `Container` and `(ptr, count)`/`(first, last)` constructors. The issue is that implicit conversions are notoriously problematic, so they should be permitted only when they are absolutely known to be safe.)

[2018-04-24 Priority set to 1 after discussion on the reflector.]

[2018-06 Rapperswil Thursday issues processing]

Status to LEWG. Should this be ill-formed, or fail at runtime if the container is too small? Discussion on the reflector here.

[2018-11 San Diego Saturday]

LEWG said that they're fine with the proposed resolution. Status to Tentatively Ready.

Proposed resolution:

This wording is relative to N4741.

> 1. Edit 22.7.3.2 [span.cons] as indicated:

>    >     template<class Container> constexpr span(Container& cont);
>    >     template<class Container> constexpr span(const Container& cont);

>    > > -14- Requires: `[data(cont), data(cont) + size(cont))` shall be a valid range. If `extent` is not equal to `dynamic_extent`, then `size(cont)` shall be equal to `extent`.

>    > > -15- Effects: Constructs a `span` that is a view over the range `[data(cont), data(cont) + size(cont))`.

>    > > -16- Postconditions: `size() == size(cont) && data() == data(cont)`.

>    > > -17- Throws: What and when `data(cont)` and `size(cont)` throw.

>    > > -18- Remarks: These constructors shall not participate in overload resolution unless:

>    > > 1. (18.?) — `extent == dynamic_extent`,

>    > > 2. (18.1) — `Container` is not a specialization of `span`,

>    > > 3. (18.2) — `Container` is not a specialization of `array`,

>    > > 4. […]