diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2024-12-11 22:56:08 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2025-01-08 12:45:37 +0000 |
commit | cbef2c1dbd0a609f68862c0a9aa9bf80a502411e (patch) | |
tree | aa9ba580bcf253cedd32e7e09cef1693c47ba0a9 /gcc | |
parent | fa6549c1f0e75ff33cb641d98af72ee354b04bbe (diff) | |
download | gcc-cbef2c1dbd0a609f68862c0a9aa9bf80a502411e.zip gcc-cbef2c1dbd0a609f68862c0a9aa9bf80a502411e.tar.gz gcc-cbef2c1dbd0a609f68862c0a9aa9bf80a502411e.tar.bz2 |
libstdc++: Avoid redundant assertions in std::span constructors
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.
Diffstat (limited to 'gcc')
0 files changed, 0 insertions, 0 deletions