libstdc++: Remove overzealous static_asserts from std::span

For a span with statically empty extent, we currently model the
preconditions of front(), back(), and operator[] as if they are
mandates, by using a static_assert to verify that extent != 0.  This
causes us to reject valid programs that would instantiate these member
functions and at runtime never call them.

Since they are already followed by more general runtime asserts, this
patch just removes these static_asserts altogether,

libstdc++-v3/ChangeLog:

	* include/std/span (span::front): Remove static_assert.
	(span::back): Likewise.
	(span::operator[]): Likewise.
	* testsuite/23_containers/span/back_neg.cc: Rewrite to verify
	that we check the preconditions of back() only when it's called.
	* testsuite/23_containers/span/front_neg.cc: Likewise for
	front().
	* testsuite/23_containers/span/index_op_neg.cc: Likewise for
	operator[].
This commit is contained in:
Patrick Palka 2020-09-21 20:53:17 -04:00
parent 813ad9c4dd
commit 37edf28c24
4 changed files with 30 additions and 15 deletions

View File

@ -264,7 +264,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr reference
front() const noexcept
{
static_assert(extent != 0);
__glibcxx_assert(!empty());
return *this->_M_ptr;
}
@ -272,7 +271,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr reference
back() const noexcept
{
static_assert(extent != 0);
__glibcxx_assert(!empty());
return *(this->_M_ptr + (size() - 1));
}
@ -280,7 +278,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr reference
operator[](size_type __idx) const noexcept
{
static_assert(extent != 0);
__glibcxx_assert(__idx < size());
return *(this->_M_ptr + __idx);
}

View File

@ -20,10 +20,16 @@
#include <span>
void
test01()
constexpr bool
test01(bool b)
{
std::span<int, 0> s;
s.back(); // { dg-error "here" }
if (b || !s.empty())
s.back();
return true;
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
static_assert(test01(false));
static_assert(test01(true)); // { dg-error "non-constant" }
// { dg-error "assert" "" { target *-*-* } 0 }
// { dg-prune-output "in 'constexpr' expansion" }

View File

@ -20,10 +20,16 @@
#include <span>
void
test01()
constexpr bool
test01(bool b)
{
std::span<int, 0> s;
s.front(); // { dg-error "here" }
if (b || !s.empty())
s.front();
return true;
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
static_assert(test01(false));
static_assert(test01(true)); // { dg-error "non-constant" }
// { dg-error "assert" "" { target *-*-* } 0 }
// { dg-prune-output "in 'constexpr' expansion" }

View File

@ -20,10 +20,16 @@
#include <span>
void
test01()
constexpr bool
test01(bool b)
{
std::span<int, 0> s;
s[99]; // { dg-error "here" }
if (b || !s.empty())
s[99];
return true;
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
static_assert(test01(false));
static_assert(test01(true)); // { dg-error "non-constant" }
// { dg-error "assert" "" { target *-*-* } 0 }
// { dg-prune-output "in 'constexpr' expansion" }