diff --git a/include/boost/core/detail/assert.hpp b/include/boost/core/detail/assert.hpp new file mode 100644 index 00000000..9e28ecc5 --- /dev/null +++ b/include/boost/core/detail/assert.hpp @@ -0,0 +1,26 @@ +/* +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(__GNUC__) && __GNUC__ < 5 && \ + !defined(__clang__) && \ + !defined(__INTEL_COMPILER) +#if defined(NDEBUG) +#define BOOST_CORE_ASSERT(expr) void(0) +#else +#define BOOST_CORE_ASSERT(expr) \ + ((expr) ? void(0) : __assert_fail(#expr, __FILE__, __LINE__, 0)) +#endif +#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 2e64262d..67323682 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 @@ class span { } 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 @@ class span { } 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 c8d302f5..593b5270 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 00000000..c24751b8 --- /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