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.