[libcxx-commits] [libcxx] 6d2599e - [libcxx][span] Implement P1976R2

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed May 13 06:53:11 PDT 2020


Author: Michael Schellenberger Costa
Date: 2020-05-13T09:52:47-04:00
New Revision: 6d2599e4f776d0cd88438cb82a00c4fc25cc3f67

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

LOG: [libcxx][span] Implement P1976R2

This resolves the NB comment about the construction of a fixed-size span
from a dynamic range.

Differential Revision: https://reviews.llvm.org/D74577

Added: 
    libcxx/test/std/language.support/support.limits/support.limits.general/span.version.pass.cpp

Modified: 
    libcxx/docs/FeatureTestMacroTable.rst
    libcxx/include/span
    libcxx/include/version
    libcxx/test/std/containers/views/span.cons/assign.pass.cpp
    libcxx/test/std/containers/views/span.cons/container.fail.cpp
    libcxx/test/std/containers/views/span.cons/container.pass.cpp
    libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp
    libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp
    libcxx/test/std/containers/views/span.cons/span.fail.cpp
    libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
    libcxx/utils/generate_feature_test_macro_components.py

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 937683d9cc12..77c7c68cf962 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -198,6 +198,8 @@ Status
     ------------------------------------------------- -----------------
     ``__cpp_lib_ranges``                              *unimplemented*  
     ------------------------------------------------- -----------------
+    ``__cpp_lib_span``                                ``202002L``      
+    ------------------------------------------------- -----------------
     ``__cpp_lib_three_way_comparison``                *unimplemented*  
     ------------------------------------------------- -----------------
     ``__cpp_lib_to_array``                            ``201907L``      

diff  --git a/libcxx/include/span b/libcxx/include/span
index 1fe1496530e9..018bf5190573 100644
--- a/libcxx/include/span
+++ b/libcxx/include/span
@@ -53,8 +53,8 @@ public:
 
     // [span.cons], span constructors, copy, assignment, and destructor
     constexpr span() noexcept;
-    constexpr span(pointer ptr, size_type count);
-    constexpr span(pointer firstElem, pointer lastElem);
+    constexpr explicit(Extent != dynamic_extent) span(pointer ptr, size_type count);
+    constexpr explicit(Extent != dynamic_extent) span(pointer firstElem, pointer lastElem);
     template <size_t N>
         constexpr span(element_type (&arr)[N]) noexcept;
     template <size_t N>
@@ -62,12 +62,12 @@ public:
     template <size_t N>
         constexpr span(const array<value_type, N>& arr) noexcept;
     template <class Container>
-        constexpr span(Container& cont);
+        constexpr explicit(Extent != dynamic_extent) span(Container& cont);
     template <class Container>
-        constexpr span(const Container& cont);
+        constexpr explicit(Extent != dynamic_extent) span(const Container& cont);
     constexpr span(const span& other) noexcept = default;
     template <class OtherElementType, size_t OtherExtent>
-        constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept;
+        constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept;
     ~span() noexcept = default;
     constexpr span& operator=(const span& other) noexcept = default;
 
@@ -214,15 +214,31 @@ public:
     constexpr span           (const span&) noexcept = default;
     constexpr span& operator=(const span&) noexcept = default;
 
-    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, size_type __count) : __data{__ptr}
+    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __ptr, size_type __count) : __data{__ptr}
         { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); }
-    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}
+    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(pointer __f, pointer __l) : __data{__f}
         { (void)__l;     _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
 
     _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent])          noexcept : __data{__arr} {}
     _LIBCPP_INLINE_VISIBILITY constexpr span(      array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
     _LIBCPP_INLINE_VISIBILITY constexpr span(const array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {}
 
+    template <class _Container>
+    _LIBCPP_INLINE_VISIBILITY
+        constexpr explicit span(      _Container& __c,
+            enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
+        : __data{_VSTD::data(__c)} {
+            _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
+        }
+
+    template <class _Container>
+    _LIBCPP_INLINE_VISIBILITY
+        constexpr explicit span(const _Container& __c,
+            enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
+        : __data{_VSTD::data(__c)} {
+            _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (range)");
+        }
+
     template <class _OtherElementType>
     _LIBCPP_INLINE_VISIBILITY
         constexpr span(const span<_OtherElementType, _Extent>& __other,
@@ -233,7 +249,7 @@ public:
 
     template <class _OtherElementType>
     _LIBCPP_INLINE_VISIBILITY
-        constexpr span(const span<_OtherElementType, dynamic_extent>& __other,
+        constexpr explicit span(const span<_OtherElementType, dynamic_extent>& __other,
                        enable_if_t<
                           is_convertible_v<_OtherElementType(*)[], element_type (*)[]>,
                           nullptr_t> = nullptr) noexcept
@@ -247,7 +263,7 @@ public:
     constexpr span<element_type, _Count> first() const noexcept
     {
         static_assert(_Count <= _Extent, "Count out of range in span::first()");
-        return {data(), _Count};
+        return span<element_type, _Count>{data(), _Count};
     }
 
     template <size_t _Count>
@@ -255,7 +271,7 @@ public:
     constexpr span<element_type, _Count> last() const noexcept
     {
         static_assert(_Count <= _Extent, "Count out of range in span::last()");
-        return {data() + size() - _Count, _Count};
+        return span<element_type, _Count>{data() + size() - _Count, _Count};
     }
 
     _LIBCPP_INLINE_VISIBILITY
@@ -279,7 +295,9 @@ public:
     {
         static_assert(_Offset <= _Extent, "Offset out of range in span::subspan()");
         static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset, "Offset + count out of range in span::subspan()");
-        return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
+
+        using _ReturnType = span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset>;
+        return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
     }
 
 
@@ -337,10 +355,10 @@ public:
     }
 
     _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept
-    { return {reinterpret_cast<const byte *>(data()), size_bytes()}; }
+    { return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte *>(data()), size_bytes()}; }
 
     _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writable_bytes() const noexcept
-    { return {reinterpret_cast<byte *>(data()), size_bytes()}; }
+    { return span<byte, _Extent * sizeof(element_type)>{reinterpret_cast<byte *>(data()), size_bytes()}; }
 
 private:
     pointer    __data;
@@ -418,7 +436,7 @@ public:
     constexpr span<element_type, _Count> first() const noexcept
     {
         _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()");
-        return {data(), _Count};
+        return span<element_type, _Count>{data(), _Count};
     }
 
     template <size_t _Count>
@@ -426,7 +444,7 @@ public:
     constexpr span<element_type, _Count> last() const noexcept
     {
         _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()");
-        return {data() + size() - _Count, _Count};
+        return span<element_type, _Count>{data() + size() - _Count, _Count};
     }
 
     _LIBCPP_INLINE_VISIBILITY
@@ -449,7 +467,7 @@ public:
     {
         _LIBCPP_ASSERT(_Offset <= size(), "Offset out of range in span::subspan()");
         _LIBCPP_ASSERT(_Count == dynamic_extent || _Count <= size() - _Offset, "Offset + count out of range in span::subspan()");
-        return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
+        return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
     }
 
     constexpr span<element_type, dynamic_extent>

diff  --git a/libcxx/include/version b/libcxx/include/version
index c2e99ccd9a90..46b0d65cb29b 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -98,6 +98,7 @@ __cpp_lib_shared_mutex                                  201505L <shared_mutex>
 __cpp_lib_shared_ptr_arrays                             201611L <memory>
 __cpp_lib_shared_ptr_weak_type                          201606L <memory>
 __cpp_lib_shared_timed_mutex                            201402L <shared_mutex>
+__cpp_lib_span                                          202002L <span>
 __cpp_lib_string_udls                                   201304L <string>
 __cpp_lib_string_view                                   201606L <string> <string_view>
 __cpp_lib_three_way_comparison                          201711L <compare>
@@ -234,8 +235,9 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # endif
 # define __cpp_lib_list_remove_return_type              201806L
 // # define __cpp_lib_ranges                               201811L
-# define __cpp_lib_to_array                                201907L
+# define __cpp_lib_span                                 202002L
 // # define __cpp_lib_three_way_comparison                 201711L
+# define __cpp_lib_to_array                             201907L
 #endif
 
 #endif // _LIBCPP_VERSIONH

diff  --git a/libcxx/test/std/containers/views/span.cons/assign.pass.cpp b/libcxx/test/std/containers/views/span.cons/assign.pass.cpp
index cde1e168431d..e0973e73034e 100644
--- a/libcxx/test/std/containers/views/span.cons/assign.pass.cpp
+++ b/libcxx/test/std/containers/views/span.cons/assign.pass.cpp
@@ -185,13 +185,14 @@ int main(int, char**)
 
 //  constexpr statically sized assignment
     {
-        constexpr std::span<const int,2> spans[] = {
-            {carr1, 2},
-            {carr1 + 1, 2},
-            {carr1 + 2, 2},
-            {carr2, 2},
-            {carr2 + 1, 2},
-            {carr3, 2}
+        using spanType = std::span<const int,2>;
+        constexpr spanType spans[] = {
+            spanType{carr1, 2},
+            spanType{carr1 + 1, 2},
+            spanType{carr1 + 2, 2},
+            spanType{carr2, 2},
+            spanType{carr2 + 1, 2},
+            spanType{carr3, 2}
             };
 
         static_assert(std::size(spans) == 6, "" );
@@ -247,10 +248,11 @@ int main(int, char**)
 
 //  statically sized assignment
     {
-        std::span<int,2> spans[] = {
-            {arr,     arr + 2},
-            {arr + 1, arr + 3},
-            {arr + 2, arr + 4}
+        using spanType = std::span<int,2>;
+        spanType spans[] = {
+            spanType{arr,     arr + 2},
+            spanType{arr + 1, arr + 3},
+            spanType{arr + 2, arr + 4}
             };
 
         for (size_t i = 0; i < std::size(spans); ++i)
@@ -279,10 +281,11 @@ int main(int, char**)
     }
 
     {
-    std::span<std::string, 1> spans[] = {
-            {strs,     strs + 1},
-            {strs + 1, strs + 2},
-            {strs + 2, strs + 3}
+    using spanType = std::span<std::string, 1>;
+    spanType spans[] = {
+            spanType{strs,     strs + 1},
+            spanType{strs + 1, strs + 2},
+            spanType{strs + 2, strs + 3}
             };
 
         for (size_t i = 0; i < std::size(spans); ++i)

diff  --git a/libcxx/test/std/containers/views/span.cons/container.fail.cpp b/libcxx/test/std/containers/views/span.cons/container.fail.cpp
index b0b753cbd2dc..81abde99be3a 100644
--- a/libcxx/test/std/containers/views/span.cons/container.fail.cpp
+++ b/libcxx/test/std/containers/views/span.cons/container.fail.cpp
@@ -63,6 +63,10 @@ struct NotAContainerPrivate {
     const T *data() const {return nullptr;}
 };
 
+template<class T, size_t extent, class container>
+std::span<T, extent> createImplicitSpan(container c) {
+    return {c}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
 
 int main(int, char**)
 {
@@ -106,12 +110,14 @@ int main(int, char**)
     std::span<      volatile int> s7{cv};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
     }
 
-//  statically sized
+// explicit constructor necessary
     {
-	IsAContainer<int> c;
-    std::span<int,1> s1{c}; // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}}
-    }
+    IsAContainer<int> c;
+    const IsAContainer<int> cc;
 
+    createImplicitSpan<int, 1>(c);
+    createImplicitSpan<int, 1>(cc);
+    }
 
   return 0;
 }

diff  --git a/libcxx/test/std/containers/views/span.cons/container.pass.cpp b/libcxx/test/std/containers/views/span.cons/container.pass.cpp
index d4758c694ee2..af28cceed9e4 100644
--- a/libcxx/test/std/containers/views/span.cons/container.pass.cpp
+++ b/libcxx/test/std/containers/views/span.cons/container.pass.cpp
@@ -84,14 +84,32 @@ constexpr bool testConstexprSpan()
     return s1.data() == val.getV() && s1.size() == 1;
 }
 
+template <typename T>
+constexpr bool testConstexprSpanStatic()
+{
+    constexpr IsAContainer<const T> val{};
+    std::span<const T, 1> s1{val};
+    return s1.data() == val.getV() && s1.size() == 1;
+}
 
 template <typename T>
 void testRuntimeSpan()
 {
     IsAContainer<T> val{};
     const IsAContainer<T> cVal;
-    std::span<T>          s1{val};
-    std::span<const T>    s2{cVal};
+    std::span<T>       s1{val};
+    std::span<const T> s2{cVal};
+    assert(s1.data() == val.getV()  && s1.size() == 1);
+    assert(s2.data() == cVal.getV() && s2.size() == 1);
+}
+
+template <typename T>
+void testRuntimeSpanStatic()
+{
+    IsAContainer<T> val{};
+    const IsAContainer<T> cVal;
+    std::span<T, 1>       s1{val};
+    std::span<const T, 1> s2{cVal};
     assert(s1.data() == val.getV()  && s1.size() == 1);
     assert(s2.data() == cVal.getV() && s2.size() == 1);
 }
@@ -105,12 +123,23 @@ int main(int, char**)
     static_assert(testConstexprSpan<double>(), "");
     static_assert(testConstexprSpan<A>(),      "");
 
+    static_assert(testConstexprSpanStatic<int>(),    "");
+    static_assert(testConstexprSpanStatic<long>(),   "");
+    static_assert(testConstexprSpanStatic<double>(), "");
+    static_assert(testConstexprSpanStatic<A>(),      "");
+
     testRuntimeSpan<int>();
     testRuntimeSpan<long>();
     testRuntimeSpan<double>();
     testRuntimeSpan<std::string>();
     testRuntimeSpan<A>();
 
+    testRuntimeSpanStatic<int>();
+    testRuntimeSpanStatic<long>();
+    testRuntimeSpanStatic<double>();
+    testRuntimeSpanStatic<std::string>();
+    testRuntimeSpanStatic<A>();
+
     checkCV();
 
   return 0;

diff  --git a/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp b/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp
index 05dbcf8d1cd5..8ec377142420 100644
--- a/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp
+++ b/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp
@@ -27,6 +27,11 @@ const          int  carr[] = {4,5,6};
       volatile int  varr[] = {7,8,9};
 const volatile int cvarr[] = {1,3,5};
 
+template<class T, size_t extent>
+std::span<T, extent> createImplicitSpan(T* ptr, size_t len) {
+    return {ptr, len}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
+
 int main(int, char**)
 {
 //  We can't check that the size doesn't match - because that's a runtime property
@@ -60,5 +65,10 @@ int main(int, char**)
     std::span<      volatile int,3> s7{cvarr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
     }
 
+// explicit constructor necessary
+    {
+    createImplicitSpan<int, 1>(arr, 1);
+    }
+
   return 0;
 }

diff  --git a/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp b/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp
index 9c15ea58c952..73ef48011744 100644
--- a/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp
+++ b/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp
@@ -27,6 +27,11 @@ const          int  carr[] = {4,5,6};
       volatile int  varr[] = {7,8,9};
 const volatile int cvarr[] = {1,3,5};
 
+template<class T, size_t extent>
+std::span<T, extent> createImplicitSpan(T* first, T* last) {
+    return {first, last}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
+
 int main(int, char**)
 {
 //  We can't check that the size doesn't match - because that's a runtime property
@@ -60,5 +65,10 @@ int main(int, char**)
     std::span<      volatile int,3> s7{cvarr, cvarr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
     }
 
+    // explicit constructor necessary
+    {
+    createImplicitSpan<int, 1>(arr, arr + 1);
+    }
+
   return 0;
 }

diff  --git a/libcxx/test/std/containers/views/span.cons/span.fail.cpp b/libcxx/test/std/containers/views/span.cons/span.fail.cpp
index c303719fd016..03ff2e636c67 100644
--- a/libcxx/test/std/containers/views/span.cons/span.fail.cpp
+++ b/libcxx/test/std/containers/views/span.cons/span.fail.cpp
@@ -24,6 +24,11 @@
 
 #include "test_macros.h"
 
+template<class T, size_t extent, size_t otherExtent>
+std::span<T, extent> createImplicitSpan(std::span<T, otherExtent> s) {
+    return {s}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
+
 void checkCV ()
 {
 //  std::span<               int>   sp;
@@ -101,5 +106,10 @@ int main(int, char**)
 
     checkCV();
 
+    // explicit constructor necessary
+    {
+    createImplicitSpan<int, 1>(sp);
+    }
+
   return 0;
 }

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.pass.cpp
new file mode 100644
index 000000000000..c1a9f8632705
--- /dev/null
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/span.version.pass.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+
+// <span>
+
+// Test the feature test macros defined by <span>
+
+/*  Constant          Value
+    __cpp_lib_span    202002L [C++2a]
+*/
+
+#include <span>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 14
+
+# ifdef __cpp_lib_span
+#   error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_span
+#   error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_span
+#   error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
+#elif TEST_STD_VER > 17
+
+# ifndef __cpp_lib_span
+#   error "__cpp_lib_span should be defined in c++2a"
+# endif
+# if __cpp_lib_span != 202002L
+#   error "__cpp_lib_span should have the value 202002L in c++2a"
+# endif
+
+#endif // TEST_STD_VER > 17
+
+int main(int, char**) { return 0; }

diff  --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
index 081f0fede234..34e59e038546 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp
@@ -85,6 +85,7 @@
     __cpp_lib_shared_ptr_arrays                    201611L [C++17]
     __cpp_lib_shared_ptr_weak_type                 201606L [C++17]
     __cpp_lib_shared_timed_mutex                   201402L [C++14]
+    __cpp_lib_span                                 202002L [C++2a]
     __cpp_lib_string_udls                          201304L [C++14]
     __cpp_lib_string_view                          201606L [C++17]
     __cpp_lib_three_way_comparison                 201711L [C++2a]
@@ -391,6 +392,10 @@
 #   error "__cpp_lib_shared_timed_mutex should not be defined before c++14"
 # endif
 
+# ifdef __cpp_lib_span
+#   error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
 # ifdef __cpp_lib_string_udls
 #   error "__cpp_lib_string_udls should not be defined before c++14"
 # endif
@@ -784,6 +789,10 @@
 #   endif
 # endif
 
+# ifdef __cpp_lib_span
+#   error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
 # ifndef __cpp_lib_string_udls
 #   error "__cpp_lib_string_udls should be defined in c++14"
 # endif
@@ -1381,6 +1390,10 @@
 #   endif
 # endif
 
+# ifdef __cpp_lib_span
+#   error "__cpp_lib_span should not be defined before c++2a"
+# endif
+
 # ifndef __cpp_lib_string_udls
 #   error "__cpp_lib_string_udls should be defined in c++17"
 # endif
@@ -2116,6 +2129,13 @@
 #   endif
 # endif
 
+# ifndef __cpp_lib_span
+#   error "__cpp_lib_span should be defined in c++2a"
+# endif
+# if __cpp_lib_span != 202002L
+#   error "__cpp_lib_span should have the value 202002L in c++2a"
+# endif
+
 # ifndef __cpp_lib_string_udls
 #   error "__cpp_lib_string_udls should be defined in c++2a"
 # endif

diff  --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 96860c2118c2..d19e358482b5 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -591,6 +591,12 @@ def add_version_header(tc):
    },
    "headers": ["array"],
    },
+  {"name": "__cpp_lib_span",
+   "values": {
+     "c++2a": int(202002),
+   },
+   "headers": ["span"],
+   },
 ]], key=lambda tc: tc["name"])
 
 def get_std_dialects():


        


More information about the libcxx-commits mailing list