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[].
(cherry picked from commit
37edf28c24b7bd198c27d266af9aefad417635fd)
constexpr reference
front() const noexcept
{
- static_assert(extent != 0);
__glibcxx_assert(!empty());
return *this->_M_ptr;
}
constexpr reference
back() const noexcept
{
- static_assert(extent != 0);
__glibcxx_assert(!empty());
return *(this->_M_ptr + (size() - 1));
}
constexpr reference
operator[](size_type __idx) const noexcept
{
- static_assert(extent != 0);
__glibcxx_assert(__idx < size());
return *(this->_M_ptr + __idx);
}
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
+#undef _GLIBCXX_ASSERTIONS
+#define _GLIBCXX_ASSERTIONS
#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" }
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
+#undef _GLIBCXX_ASSERTIONS
+#define _GLIBCXX_ASSERTIONS
#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" }
// { dg-options "-std=gnu++2a" }
// { dg-do compile { target c++2a } }
+#undef _GLIBCXX_ASSERTIONS
+#define _GLIBCXX_ASSERTIONS
#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" }