llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-libcxx Author: Hristo Hristov (H-G-Hristov) <details> <summary>Changes</summary> Implements: [P2821R5](https://wg21.link/P2821R5) --- Full diff: https://github.com/llvm/llvm-project/pull/74994.diff 5 Files Affected: - (modified) libcxx/docs/ReleaseNotes/18.rst (+1) - (modified) libcxx/docs/Status/Cxx2cPapers.csv (+1-1) - (modified) libcxx/include/span (+30) - (added) libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp (+136) - (modified) libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp (-1) ``````````diff diff --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst index 9e509db6359c4a..f3e8281e74da2f 100644 --- a/libcxx/docs/ReleaseNotes/18.rst +++ b/libcxx/docs/ReleaseNotes/18.rst @@ -55,6 +55,7 @@ Implemented Papers - P2871R3 - Remove Deprecated Unicode Conversion Facets from C++26 - P2870R3 - Remove basic_string::reserve() - P2909R4 - Fix formatting of code units as integers (Dude, where’s my ``char``?) +- P2821R5 - span.at() Improvements and New Features diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index ff83648aa76830..fa4a112d143673 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -35,7 +35,7 @@ "`P2909R4 <https://wg21.link/P2909R4>`__","LWG","Fix formatting of code units as integers (Dude, where’s my ``char``?)","Kona November 2023","|Complete|","18.0","|format| |DR|" "`P0952R2 <https://wg21.link/P0952R2>`__","LWG","A new specification for ``std::generate_canonical``","Kona November 2023","","","" "`P2447R6 <https://wg21.link/P2447R6>`__","LWG","``std::span`` over an initializer list","Kona November 2023","","","" -"`P2821R5 <https://wg21.link/P2821R5>`__","LWG","``span.at()``","Kona November 2023","","","" +"`P2821R5 <https://wg21.link/P2821R5>`__","LWG","``span.at()``","Kona November 2023","|Complete|","18.0","" "`P2868R3 <https://wg21.link/P2868R3>`__","LWG","Remove Deprecated ``std::allocator`` Typedef From C++26","Kona November 2023","","","" "`P2870R3 <https://wg21.link/P2870R3>`__","LWG","Remove ``basic_string::reserve()`` From C++26","Kona November 2023","|Complete|","18.0","" "`P2871R3 <https://wg21.link/P2871R3>`__","LWG","Remove Deprecated Unicode Conversion Facets from C++26","Kona November 2023","|Complete|","18.0","" diff --git a/libcxx/include/span b/libcxx/include/span index f94bda40fa7350..9af8dabb3ebd34 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -92,6 +92,7 @@ public: // [span.elem], span element access constexpr reference operator[](size_type idx) const; + constexpr reference at(size_type idx) const; // since C++26 constexpr reference front() const; constexpr reference back() const; constexpr pointer data() const noexcept; @@ -146,6 +147,9 @@ template<class R> #include <__utility/forward.h> #include <array> // for array #include <cstddef> // for byte +#if _LIBCPP_STD_VER >= 26 +# include <stdexcept> +#endif #include <version> // standard-mandated includes @@ -343,6 +347,15 @@ public: return __data_[__idx]; } +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __idx) const { + if (__idx >= size()) { + __throw_out_of_range(); + } + return *(data() + __idx); + } +# endif + _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span"); @@ -383,6 +396,10 @@ public: private: pointer __data_; + +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("span"); } +# endif }; @@ -510,6 +527,15 @@ public: return __data_[__idx]; } +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __idx) const { + if (__idx >= size()) { + __throw_out_of_range(); + } + return *(data() + __idx); + } +# endif + _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept { _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::front() on empty span"); @@ -552,6 +578,10 @@ public: private: pointer __data_; size_type __size_; + +# if _LIBCPP_STD_VER >= 26 + _LIBCPP_NORETURN _LIBCPP_HIDE_FROM_ABI void __throw_out_of_range() const { std::__throw_out_of_range("span"); } +# endif }; template <class _Tp, size_t _Extent> diff --git a/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp new file mode 100644 index 00000000000000..75a45171185cf3 --- /dev/null +++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23 + +// <span> + +// constexpr reference at(size_type idx) const; // since C++26 + +#include <array> +#include <cassert> +#include <concepts> +#include <span> +#include <stdexcept> +#include <utility> +#include <vector> + +#include "test_macros.h" + +constexpr void testSpanAt(auto span, int idx, int expectedValue) { + // non-const + { + std::same_as<typename decltype(span)::reference> decltype(auto) elem = span.at(idx); + assert(elem == expectedValue); + } + + // const + { + std::same_as<typename decltype(span)::reference> decltype(auto) elem = std::as_const(span).at(idx); + assert(elem == expectedValue); + } +} + +constexpr bool test() { + // With static extent + { + std::array arr{0, 1, 2, 3, 4, 5, 9084}; + std::span arrSpan{arr}; + + assert(std::dynamic_extent != arrSpan.extent); + + testSpanAt(arrSpan, 0, 0); + testSpanAt(arrSpan, 1, 1); + testSpanAt(arrSpan, 6, 9084); + } + + // With dynamic extent + { + std::vector vec{0, 1, 2, 3, 4, 5, 9084}; + std::span vecSpan{vec}; + + assert(std::dynamic_extent == vecSpan.extent); + + testSpanAt(vecSpan, 0, 0); + testSpanAt(vecSpan, 1, 1); + testSpanAt(vecSpan, 6, 9084); + } + + return true; +} + +void test_exceptions() { +#ifndef TEST_HAS_NO_EXCEPTIONS + // With static extent + { + std::array arr{1, 2, 3, 4}; + const std::span arrSpan{arr}; + + try { + TEST_IGNORE_NODISCARD arrSpan.at(arr.size() + 1); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + { + std::array<int, 0> arr{}; + const std::span arrSpan{arr}; + + try { + TEST_IGNORE_NODISCARD arrSpan.at(0); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + // With dynamic extent + + { + std::vector vec{1, 2, 3, 4}; + const std::span vecSpan{vec}; + + try { + TEST_IGNORE_NODISCARD vecSpan.at(vec.size() + 1); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } + + { + std::vector<int> vec{}; + const std::span vecSpan{vec}; + + try { + TEST_IGNORE_NODISCARD vecSpan.at(0); + assert(false); + } catch (std::out_of_range const&) { + // pass + } catch (...) { + assert(false); + } + } +#endif // TEST_HAS_NO_EXCEPTIONS +} + +int main(int, char**) { + test(); + test_exceptions(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp b/libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp index e46fd267ef5cc5..b7f36c57585881 100644 --- a/libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp +++ b/libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp @@ -41,7 +41,6 @@ void testRuntimeSpan(Span sp, std::size_t idx) assert(r1 == r2); } -struct A{}; constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; `````````` </details> https://github.com/llvm/llvm-project/pull/74994 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits