On Thu, 12 Dec 2024 at 00:05, Jonathan Wakely <jwak...@redhat.com> wrote:
>
> Any std::span<T, N> constructor with a runtime length has a precondition
> that the length is equal to N (except when N == std::dynamic_extent).
>
> Currently every constructor with a runtime length does:
>
> if constexpr (extent != dynamic_extent)
>   __glibcxx_assert(n == extent);
>
> We can move those assertions into the __detail::__extent_storage<N>
> constructor so they are only done in one place. To avoid checking the
> assertions when we have a constant length we can add a second
> constructor which is consteval and takes a integral_constant<size_t, N>
> argument. The std::span constructors can pass a size_t for runtime
> lengths and a std::integral_constant<size_t, N> for constant lengths
> that don't need to be checked.
>
> The __detail::__extent_storage<dynamic_extent> specialization only needs
> one constructor, as a std::integral_constant<size_t, N> argument can
> implicitly convert to size_t.
>
> For the member functions that return a subspan with a constant extent we
> return std::span<T,C>(ptr, C) which is redundant in two ways. Repeating
> the constant length C when it's already a template argument is
> redundant, and using the std::span(T*, size_t) constructor implies a
> runtime length which will do a redundant assertion check.  Even though
> that assertion won't fail and should be optimized away, it's still
> unnecessary code that doesn't need to be instantiated and then optimized
> away again. We can avoid that by adding a new private constructor that
> only takes a pointer (wrapped in a custom tag struct to avoid
> accidentally using that constructor) and automatically sets _M_extent to
> the correct value.
>
> libstdc++-v3/ChangeLog:
>
>         * include/std/span (__detail::__extent_storage): Check
>         precondition in constructor. Add consteval constructor for valid
>         lengths and deleted constructor for invalid constant lengths.
>         Make member functions always_inline.
>         (__detail::__span_ptr): New class template.
>         (span): Adjust constructors to use a std::integral_constant
>         value for constant lengths. Declare all specializations of
>         std::span as friends.
>         (span::first<C>, span::last<C>, span::subspan<O,C>): Use new
>         private constructor.
>         (span(__span_ptr<T>)): New private constructor for constant
>         lengths.
> ---
>
> As suggested at
> https://gcc.gnu.org/pipermail/gcc-patches/2024-December/671431.html
>
> Tested x86_64-linux.

Pushed to trunk now.

Reply via email to