From 24a8174ef1c9b56226e5478ad65a913e28b79bda Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Thu, 16 Jan 2025 19:12:31 -0500 Subject: [PATCH] Add asserts to span --- include/boost/core/detail/assert.hpp | 24 ++++++++++ include/boost/core/span.hpp | 19 +++++--- test/Jamfile.v2 | 1 + test/span_constexpr_test.cpp | 72 ++++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 include/boost/core/detail/assert.hpp create mode 100644 test/span_constexpr_test.cpp diff --git a/include/boost/core/detail/assert.hpp b/include/boost/core/detail/assert.hpp new file mode 100644 index 0000000..a5c2108 --- /dev/null +++ b/include/boost/core/detail/assert.hpp @@ -0,0 +1,24 @@ +/* +Copyright 2025 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#ifndef BOOST_CORE_DETAIL_ASSERT_HPP +#define BOOST_CORE_DETAIL_ASSERT_HPP + +#include + +#if !defined(NDEBUG) && \ + !defined(__clang__) && \ + !defined(__INTEL_COMPILER) && \ + defined(__GNUC__) && \ + (__GNUC__ < 5) +#define BOOST_CORE_ASSERT(expr) \ + ((expr) ? void(0) : __assert_fail(#expr, __FILE__, __LINE__, 0)) +#else +#define BOOST_CORE_ASSERT(expr) assert(expr) +#endif + +#endif diff --git a/include/boost/core/span.hpp b/include/boost/core/span.hpp index 2e64262..6732368 100644 --- a/include/boost/core/span.hpp +++ b/include/boost/core/span.hpp @@ -8,6 +8,7 @@ Distributed under the Boost Software License, Version 1.0. #ifndef BOOST_CORE_SPAN_HPP #define BOOST_CORE_SPAN_HPP +#include #include #include #include @@ -274,17 +275,21 @@ public: } constexpr span first(size_type c) const { - return span(s_.p, c); + return BOOST_CORE_ASSERT(c <= size()), + span(s_.p, c); } constexpr span last(size_type c) const { - return span(s_.p + (s_.n - c), c); + return BOOST_CORE_ASSERT(c <= size()), + span(s_.p + (s_.n - c), c); } constexpr span subspan(size_type o, size_type c = dynamic_extent) const { - return span(s_.p + o, - c == dynamic_extent ? s_.n - o : c); + return BOOST_CORE_ASSERT(o <= size() && + (c == dynamic_extent || c + o <= size())), + span(s_.p + o, + c == dynamic_extent ? s_.n - o : c); } constexpr size_type size() const noexcept { @@ -300,15 +305,15 @@ public: } constexpr reference operator[](size_type i) const { - return s_.p[i]; + return BOOST_CORE_ASSERT(i < size()), s_.p[i]; } constexpr reference front() const { - return *s_.p; + return BOOST_CORE_ASSERT(!empty()), *s_.p; } constexpr reference back() const { - return s_.p[s_.n - 1]; + return BOOST_CORE_ASSERT(!empty()), s_.p[s_.n - 1]; } constexpr pointer data() const noexcept { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c8d302f..593b527 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -409,6 +409,7 @@ run span_test.cpp ; run span_types_test.cpp ; run span_constructible_test.cpp ; run span_deduction_guide_test.cpp ; +run span_constexpr_test.cpp ; run as_bytes_test.cpp ; run as_writable_bytes_test.cpp ; compile span_boost_begin_test.cpp ; diff --git a/test/span_constexpr_test.cpp b/test/span_constexpr_test.cpp new file mode 100644 index 0000000..c24751b --- /dev/null +++ b/test/span_constexpr_test.cpp @@ -0,0 +1,72 @@ +/* +Copyright 2025 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#if !defined(BOOST_NO_CXX11_CONSTEXPR) +#include +#include + +constexpr const int array[4]{ 5, 10, 15, 20 }; + +void test_first() +{ + constexpr boost::span s = + boost::span(array, 4).first(2); + BOOST_TEST_EQ(s.data(), &array[0]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_last() +{ + constexpr boost::span s = + boost::span(array, 4).last(2); + BOOST_TEST_EQ(s.data(), &array[2]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_subspan() +{ + constexpr boost::span s = + boost::span(array, 4).subspan(1, 2); + BOOST_TEST_EQ(s.data(), &array[1]); + BOOST_TEST_EQ(s.size(), 2); +} + +void test_index() +{ + constexpr const int i = boost::span(array, 4)[1]; + BOOST_TEST_EQ(i, 10); +} + +void test_front() +{ + constexpr const int i = boost::span(array, 4).front(); + BOOST_TEST_EQ(i, 5); +} + +void test_back() +{ + constexpr const int i = boost::span(array, 4).back(); + BOOST_TEST_EQ(i, 20); +} + +int main() +{ + test_first(); + test_last(); + test_subspan(); + test_index(); + test_front(); + test_back(); + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif