[libc-commits] [libc] f890f80 - [libc] Allow span views over mutable data

Guillaume Chatelet via libc-commits libc-commits at lists.llvm.org
Mon Aug 22 02:43:22 PDT 2022


Author: Guillaume Chatelet
Date: 2022-08-22T09:43:08Z
New Revision: f890f80d67664b2d7ddb2acae5b29ac5e8a88950

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

LOG: [libc] Allow span views over mutable data

Added: 
    

Modified: 
    libc/src/__support/CPP/span.h
    libc/test/src/__support/CPP/span_test.cpp

Removed: 
    


################################################################################
diff  --git a/libc/src/__support/CPP/span.h b/libc/src/__support/CPP/span.h
index 5aab1bb76a60..dc3960e75f61 100644
--- a/libc/src/__support/CPP/span.h
+++ b/libc/src/__support/CPP/span.h
@@ -24,6 +24,15 @@ namespace __llvm_libc::cpp {
 //   inherits from B),
 // - No reverse iterators
 template <typename T> class span {
+  template <typename U>
+  inline static constexpr bool is_const_view_v =
+      !cpp::is_const_v<U> && cpp::is_const_v<T> &&
+      cpp::is_same_v<U, remove_cv_t<T>>;
+
+  template <typename U>
+  inline static constexpr bool is_compatible_v =
+      cpp::is_same_v<U, T> || is_const_view_v<U>;
+
 public:
   using element_type = T;
   using value_type = remove_cv_t<T>;
@@ -45,21 +54,25 @@ template <typename T> class span {
   constexpr span(pointer first, pointer end)
       : span_data(first), span_size(end - first) {}
 
-  template <size_t N>
-  constexpr span(element_type (&arr)[N]) : span_data(arr), span_size(N) {}
+  template <typename U, size_t N,
+            cpp::enable_if_t<is_compatible_v<U>, bool> = true>
+  constexpr span(U (&arr)[N]) : span_data(arr), span_size(N) {}
 
-  template <size_t N>
-  constexpr span(array<T, N> &arr)
+  template <typename U, size_t N,
+            cpp::enable_if_t<is_compatible_v<U>, bool> = true>
+  constexpr span(array<U, N> &arr)
       : span_data(arr.data()), span_size(arr.size()) {}
 
-  template <typename U,
-            cpp::enable_if_t<!cpp::is_const_v<U> && cpp::is_const_v<T> &&
-                                 cpp::is_same_v<U, value_type>,
-                             bool> = true>
-  constexpr span(span<U> &s) : span(s.data(), s.size()) {}
+  template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true>
+  constexpr span(span<U> &s) : span_data(s.data()), span_size(s.size()) {}
+
+  template <typename U, cpp::enable_if_t<is_compatible_v<U>, bool> = true>
+  constexpr span &operator=(span<U> &s) {
+    span_data = s.data();
+    span_size = s.size();
+    return *this;
+  }
 
-  constexpr span(const span &s) = default;
-  constexpr span &operator=(const span &s) = default;
   ~span() = default;
   constexpr reference operator[](size_type index) const {
     return data()[index];

diff  --git a/libc/test/src/__support/CPP/span_test.cpp b/libc/test/src/__support/CPP/span_test.cpp
index 831188d427de..c0da1cf1ce78 100644
--- a/libc/test/src/__support/CPP/span_test.cpp
+++ b/libc/test/src/__support/CPP/span_test.cpp
@@ -56,14 +56,47 @@ TEST(LlvmLibcSpanTest, InitializeArray) {
   ASSERT_EQ(s[2], 3);
 }
 
-TEST(LlvmLibcSpanTest, ConstFromMutable) {
+TEST(LlvmLibcSpanTest, InitializeViewFormMutableSingleton) {
+  int a = 42;
+  span<const int> s(&a, 1);
+  ASSERT_EQ(s.size(), size_t(1));
+  ASSERT_TRUE(s.data() == &a);
+}
+
+TEST(LlvmLibcSpanTest, InitializeViewFormMutableCArray) {
+  int a[] = {1, 2, 3};
+  span<const int> s(a);
+  ASSERT_EQ(s.size(), size_t(3));
+  ASSERT_EQ(s[0], 1);
+  ASSERT_EQ(s[1], 2);
+  ASSERT_EQ(s[2], 3);
+}
+
+TEST(LlvmLibcSpanTest, InitializeViewFormMutableArray) {
   array<int, 3> a = {1, 2, 3};
-  span<int> mutable_view(a);
-  span<const int> const_view(mutable_view);
-  ASSERT_EQ(const_view.size(), size_t(3));
-  ASSERT_EQ(const_view[0], 1);
-  ASSERT_EQ(const_view[1], 2);
-  ASSERT_EQ(const_view[2], 3);
+  span<const int> s(a);
+  ASSERT_EQ(s.size(), size_t(3));
+  ASSERT_EQ(s[0], 1);
+  ASSERT_EQ(s[1], 2);
+  ASSERT_EQ(s[2], 3);
+}
+
+TEST(LlvmLibcSpanTest, InitializeFromMutable) {
+  span<int> s;
+  span<const int> view(s);
+  (void)view;
+}
+
+TEST(LlvmLibcSpanTest, Assign) {
+  span<int> s;
+  span<int> other;
+  other = s;
+}
+
+TEST(LlvmLibcSpanTest, AssignFromMutable) {
+  span<int> s;
+  span<const int> view;
+  view = s;
 }
 
 TEST(LlvmLibcSpanTest, Modify) {


        


More information about the libc-commits mailing list