[libcxx-commits] [libcxx] a72ab9c - [libc++][span] P2821R5: `span.at()` (#74994)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Jan 5 01:41:26 PST 2024


Author: Hristo Hristov
Date: 2024-01-05T11:41:22+02:00
New Revision: a72ab9c14d604ae857acad5ed7d6b5be6914c619

URL: https://github.com/llvm/llvm-project/commit/a72ab9c14d604ae857acad5ed7d6b5be6914c619
DIFF: https://github.com/llvm/llvm-project/commit/a72ab9c14d604ae857acad5ed7d6b5be6914c619.diff

LOG: [libc++][span] P2821R5: `span.at()` (#74994)

- Implements: [P2821R5: span.at()](https://wg21.link/P2821R5)
  (https://eel.is/c++draft/views.contiguous#views.span)
- Cleaned up `span.operator[]` test

---------

Co-authored-by: Zingam <zingam at outlook.com>

Added: 
    libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/docs/ReleaseNotes/18.rst
    libcxx/docs/Status/Cxx2cPapers.csv
    libcxx/include/span
    libcxx/include/version
    libcxx/test/libcxx/transitive_includes/cxx03.csv
    libcxx/test/libcxx/transitive_includes/cxx11.csv
    libcxx/test/libcxx/transitive_includes/cxx14.csv
    libcxx/test/libcxx/transitive_includes/cxx17.csv
    libcxx/test/libcxx/transitive_includes/cxx20.csv
    libcxx/test/libcxx/transitive_includes/cxx23.csv
    libcxx/test/libcxx/transitive_includes/cxx26.csv
    libcxx/test/std/containers/views/views.span/span.elem/op_idx.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/span.version.compile.pass.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index ad12b109023154..8ce5ec9f64ef9a 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -436,6 +436,8 @@ Status
     --------------------------------------------------- -----------------
     ``__cpp_lib_smart_ptr_owner_equality``              *unimplemented*
     --------------------------------------------------- -----------------
+    ``__cpp_lib_span_at``                               ``202311L``
+    --------------------------------------------------- -----------------
     ``__cpp_lib_span_initializer_list``                 *unimplemented*
     --------------------------------------------------- -----------------
     ``__cpp_lib_sstream_from_string_view``              *unimplemented*

diff  --git a/libcxx/docs/ReleaseNotes/18.rst b/libcxx/docs/ReleaseNotes/18.rst
index f5cda9aaa5dcb0..cae2347be5fd61 100644
--- a/libcxx/docs/ReleaseNotes/18.rst
+++ b/libcxx/docs/ReleaseNotes/18.rst
@@ -57,6 +57,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()
 - P0521R0 - Proposed Resolution for CA 14 (shared_ptr use_count/unique)
 
 

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 7dd53110ac2927..007a32597f965b 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,7 @@ template<class R>
 #include <__utility/forward.h>
 #include <array>   // for array
 #include <cstddef> // for byte
+#include <stdexcept>
 #include <version>
 
 // standard-mandated includes
@@ -321,6 +323,14 @@ public:
     return __data_[__idx];
   }
 
+#  if _LIBCPP_STD_VER >= 26
+  _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
+    if (__index >= size())
+      std::__throw_out_of_range("span");
+    return __data_[__index];
+  }
+#  endif
+
   _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span");
     return __data_[0];
@@ -469,6 +479,14 @@ public:
     return __data_[__idx];
   }
 
+#  if _LIBCPP_STD_VER >= 26
+  _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
+    if (__index >= size())
+      std::__throw_out_of_range("span");
+    return __data_[__index];
+  }
+#  endif
+
   _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::front() on empty span");
     return __data_[0];

diff  --git a/libcxx/include/version b/libcxx/include/version
index 768710ef5c84aa..d3c2791a7d0b2c 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -201,6 +201,7 @@ __cpp_lib_smart_ptr_for_overwrite                       202002L <memory>
 __cpp_lib_smart_ptr_owner_equality                      202306L <memory>
 __cpp_lib_source_location                               201907L <source_location>
 __cpp_lib_span                                          202002L <span>
+__cpp_lib_span_at                                       202311L <span>
 __cpp_lib_span_initializer_list                         202311L <span>
 __cpp_lib_spanstream                                    202106L <spanstream>
 __cpp_lib_ssize                                         201902L <iterator>
@@ -505,6 +506,7 @@ __cpp_lib_within_lifetime                               202306L <type_traits>
 // # define __cpp_lib_rcu                                  202306L
 // # define __cpp_lib_saturation_arithmetic                202311L
 // # define __cpp_lib_smart_ptr_owner_equality             202306L
+# define __cpp_lib_span_at                              202311L
 // # define __cpp_lib_span_initializer_list                202311L
 // # define __cpp_lib_sstream_from_string_view             202306L
 // # define __cpp_lib_submdspan                            202306L

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index 3f066342717624..e709628ce2311b 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -742,6 +742,7 @@ span functional
 span initializer_list
 span iterator
 span limits
+span stdexcept
 span type_traits
 span version
 sstream cstddef

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 7b443e5a0ec0f9..d3ea6ed97367e4 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -748,6 +748,7 @@ span functional
 span initializer_list
 span iterator
 span limits
+span stdexcept
 span type_traits
 span version
 sstream cstddef

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index a5b77ec79bb5c3..3e56017bfb537b 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -750,6 +750,7 @@ span functional
 span initializer_list
 span iterator
 span limits
+span stdexcept
 span type_traits
 span version
 sstream cstddef

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index a5b77ec79bb5c3..3e56017bfb537b 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -750,6 +750,7 @@ span functional
 span initializer_list
 span iterator
 span limits
+span stdexcept
 span type_traits
 span version
 sstream cstddef

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index c8c84867fda459..0c5b9721a22551 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -755,6 +755,7 @@ span functional
 span initializer_list
 span iterator
 span limits
+span stdexcept
 span type_traits
 span version
 sstream cstddef

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index a4fa50dc014aba..0d8c3fa21b2f37 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -519,6 +519,7 @@ span array
 span cstddef
 span initializer_list
 span limits
+span stdexcept
 span version
 sstream cstddef
 sstream istream

diff  --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index a4fa50dc014aba..0d8c3fa21b2f37 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -519,6 +519,7 @@ span array
 span cstddef
 span initializer_list
 span limits
+span stdexcept
 span version
 sstream cstddef
 sstream istream

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..c09571675c0ffa
--- /dev/null
+++ b/libcxx/test/std/containers/views/views.span/span.elem/at.pass.cpp
@@ -0,0 +1,188 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 <limits>
+#include <span>
+#include <stdexcept>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include "test_macros.h"
+
+template <typename ReferenceT>
+constexpr void testSpanAt(auto&& anySpan, int index, int expectedValue) {
+  // non-const
+  {
+    std::same_as<ReferenceT> decltype(auto) elem = anySpan.at(index);
+    assert(elem == expectedValue);
+  }
+
+  // const
+  {
+    std::same_as<ReferenceT> decltype(auto) elem = std::as_const(anySpan).at(index);
+    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);
+
+    using ReferenceT = typename decltype(arrSpan)::reference;
+
+    testSpanAt<ReferenceT>(arrSpan, 0, 0);
+    testSpanAt<ReferenceT>(arrSpan, 1, 1);
+    testSpanAt<ReferenceT>(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);
+
+    using ReferenceT = typename decltype(vecSpan)::reference;
+
+    testSpanAt<ReferenceT>(vecSpan, 0, 0);
+    testSpanAt<ReferenceT>(vecSpan, 1, 1);
+    testSpanAt<ReferenceT>(vecSpan, 6, 9084);
+  }
+
+  return true;
+}
+
+void test_exceptions() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+  using namespace std::string_literals;
+
+  // With static extent
+  {
+    std::array arr{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()};
+    const std::span arrSpan{arr};
+
+    try {
+      using SizeT = typename decltype(arrSpan)::size_type;
+      std::ignore = arrSpan.at(std::numeric_limits<SizeT>::max());
+      assert(false);
+    } catch ([[maybe_unused]] const std::out_of_range& e) {
+      // pass
+      LIBCPP_ASSERT(e.what() == "span"s);
+    } catch (...) {
+      assert(false);
+    }
+
+    try {
+      std::ignore = arrSpan.at(arr.size());
+      assert(false);
+    } catch ([[maybe_unused]] const std::out_of_range& e) {
+      // pass
+      LIBCPP_ASSERT(e.what() == "span"s);
+    } catch (...) {
+      assert(false);
+    }
+
+    try {
+      std::ignore = arrSpan.at(arr.size() - 1);
+      // pass
+      assert(arrSpan.at(arr.size() - 1) == std::numeric_limits<int>::max());
+    } catch (...) {
+      assert(false);
+    }
+  }
+
+  {
+    std::array<int, 0> arr{};
+    const std::span arrSpan{arr};
+
+    try {
+      std::ignore = arrSpan.at(0);
+      assert(false);
+    } catch ([[maybe_unused]] const std::out_of_range& e) {
+      // pass
+      LIBCPP_ASSERT(e.what() == "span"s);
+    } catch (...) {
+      assert(false);
+    }
+  }
+
+  // With dynamic extent
+
+  {
+    std::vector vec{0, 1, 2, 3, 4, 5, 9084, std::numeric_limits<int>::max()};
+    const std::span vecSpan{vec};
+
+    try {
+      using SizeT = typename decltype(vecSpan)::size_type;
+      std::ignore = vecSpan.at(std::numeric_limits<SizeT>::max());
+      assert(false);
+    } catch ([[maybe_unused]] const std::out_of_range& e) {
+      // pass
+      LIBCPP_ASSERT(e.what() == "span"s);
+    } catch (...) {
+      assert(false);
+    }
+
+    try {
+      std::ignore = vecSpan.at(vec.size());
+      assert(false);
+    } catch (const std::out_of_range& e) {
+      // pass
+      LIBCPP_ASSERT(e.what() == "span"s);
+    } catch (...) {
+      assert(false);
+    }
+
+    try {
+      std::ignore = vecSpan.at(vec.size() - 1);
+      assert(vecSpan.at(vec.size() - 1) == std::numeric_limits<int>::max());
+    } catch (...) {
+      assert(false);
+    }
+  }
+
+  {
+    std::vector<int> vec{};
+    const std::span vecSpan{vec};
+
+    try {
+      std::ignore = vecSpan.at(0);
+      assert(false);
+    } catch ([[maybe_unused]] const std::out_of_range& e) {
+      // pass
+      LIBCPP_ASSERT(e.what() == "span"s);
+    } catch (...) {
+      assert(false);
+    }
+  }
+#endif // TEST_HAS_NO_EXCEPTIONS
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  test_exceptions();
+
+  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};
 

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.compile.pass.cpp
index 355eb1338d945e..dbbbaf4ec7c228 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.compile.pass.cpp
@@ -17,6 +17,7 @@
 
 /*  Constant                           Value
     __cpp_lib_span                     202002L [C++20]
+    __cpp_lib_span_at                  202311L [C++26]
     __cpp_lib_span_initializer_list    202311L [C++26]
 */
 
@@ -29,6 +30,10 @@
 #   error "__cpp_lib_span should not be defined before c++20"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -39,6 +44,10 @@
 #   error "__cpp_lib_span should not be defined before c++20"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -49,6 +58,10 @@
 #   error "__cpp_lib_span should not be defined before c++20"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -62,6 +75,10 @@
 #   error "__cpp_lib_span should have the value 202002L in c++20"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -75,6 +92,10 @@
 #   error "__cpp_lib_span should have the value 202002L in c++23"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -88,6 +109,13 @@
 #   error "__cpp_lib_span should have the value 202002L in c++26"
 # endif
 
+# ifndef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should be defined in c++26"
+# endif
+# if __cpp_lib_span_at != 202311L
+#   error "__cpp_lib_span_at should have the value 202311L in c++26"
+# endif
+
 # if !defined(_LIBCPP_VERSION)
 #   ifndef __cpp_lib_span_initializer_list
 #     error "__cpp_lib_span_initializer_list should be defined in c++26"

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 650a14b019ed87..3b7f2d26feebd0 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -186,6 +186,7 @@
     __cpp_lib_smart_ptr_owner_equality               202306L [C++26]
     __cpp_lib_source_location                        201907L [C++20]
     __cpp_lib_span                                   202002L [C++20]
+    __cpp_lib_span_at                                202311L [C++26]
     __cpp_lib_span_initializer_list                  202311L [C++26]
     __cpp_lib_spanstream                             202106L [C++23]
     __cpp_lib_ssize                                  201902L [C++20]
@@ -879,6 +880,10 @@
 #   error "__cpp_lib_span should not be defined before c++20"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -1716,6 +1721,10 @@
 #   error "__cpp_lib_span should not be defined before c++20"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -2733,6 +2742,10 @@
 #   error "__cpp_lib_span should not be defined before c++20"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -4029,6 +4042,10 @@
 #   error "__cpp_lib_span should have the value 202002L in c++20"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -5541,6 +5558,10 @@
 #   error "__cpp_lib_span should have the value 202002L in c++23"
 # endif
 
+# ifdef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should not be defined before c++26"
+# endif
+
 # ifdef __cpp_lib_span_initializer_list
 #   error "__cpp_lib_span_initializer_list should not be defined before c++26"
 # endif
@@ -7272,6 +7293,13 @@
 #   error "__cpp_lib_span should have the value 202002L in c++26"
 # endif
 
+# ifndef __cpp_lib_span_at
+#   error "__cpp_lib_span_at should be defined in c++26"
+# endif
+# if __cpp_lib_span_at != 202311L
+#   error "__cpp_lib_span_at should have the value 202311L in c++26"
+# endif
+
 # if !defined(_LIBCPP_VERSION)
 #   ifndef __cpp_lib_span_initializer_list
 #     error "__cpp_lib_span_initializer_list should be defined in c++26"

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 2f506f32f565cb..3ad5170d73ffec 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1085,6 +1085,11 @@ def add_version_header(tc):
             },
             "headers": ["span"],
         },
+        {
+            "name": "__cpp_lib_span_at",
+            "values": {"c++26": 202311},  # P2821R3 span.at()
+            "headers": ["span"],
+        },
         {
             "name": "__cpp_lib_span_initializer_list",
             "values": {"c++26": 202311},  # P2447R6 std::span over an initializer list


        


More information about the libcxx-commits mailing list