[clang] [llvm] [libcxx] [flang] [lldb] [libcxxabi] [libunwind] [compiler-rt] [libc] [clang-tools-extra] [libc++][span] P2447R4: `std::span` over an initializer list (PR #78157)

Mark de Wever via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 18 08:46:22 PST 2024


================
@@ -5,39 +5,134 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
+
 // UNSUPPORTED: c++03, c++11, c++14, c++17
 
 // <span>
 
-#include <span>
+// constexpr explicit(extent != dynamic_extent) span(std::initializer_list<value_type> il); // Since C++26
+
+#include <any>
 #include <cassert>
 #include <cstddef>
+#include <initializer_list>
+#include <span>
+#include <type_traits>
+
+#include "test_convertible.h"
+#include "test_macros.h"
+
+#if TEST_STD_VER >= 26
+
+// SFINAE
+
+template <typename T>
+concept ConstElementType = std::is_const_v<typename T::element_type>;
+
+static_assert(ConstElementType<std::span<const int>>);
+static_assert(!ConstElementType<std::span<int>>);
+static_assert(ConstElementType<std::span<const int, 94>>);
+static_assert(!ConstElementType<std::span<int, 94>>);
+
+// Constructor constraings
+
+template <typename I, typename T, std::size_t... N>
+concept HasInitializerListCtr = requires(I il) { std::span<T, N...>{il}; };
+
+static_assert(HasInitializerListCtr<std::initializer_list<const int>, const int>);
+static_assert(!HasInitializerListCtr<std::initializer_list<int>, int>);
+static_assert(HasInitializerListCtr<std::initializer_list<const int>, const int, 94>);
+static_assert(!HasInitializerListCtr<std::initializer_list<int>, int, 94>);
+
+// Constructor conditionally explicit
+
+static_assert(!test_convertible<std::span<const int, 28>, std::initializer_list<int>>(),
+              "This constructor must be explicit");
+static_assert(std::is_constructible_v<std::span<const int, 28>, std::initializer_list<int>>);
+static_assert(test_convertible<std::span<const int>, std::initializer_list<int>>(),
+              "This constructor must not be explicit");
+static_assert(std::is_constructible_v<std::span<const int>, std::initializer_list<int>>);
+
+#endif
 
 struct Sink {
-    constexpr Sink() = default;
-    constexpr Sink(Sink*) {}
+  constexpr Sink() = default;
+  constexpr Sink(Sink*) {}
 };
 
-constexpr std::size_t count(std::span<const Sink> sp) {
-    return sp.size();
-}
+constexpr std::size_t count(std::span<const Sink> sp) { return sp.size(); }
 
-template<int N>
-constexpr std::size_t countn(std::span<const Sink, N> sp) {
-    return sp.size();
+template <std::size_t N>
+constexpr std::size_t count_n(std::span<const Sink, N> sp) {
+  return sp.size();
 }
 
 constexpr bool test() {
+#if TEST_STD_VER >= 26
+  // Dynamic extent
+  {
+    Sink a[10];
+
+    assert(count({a}) == 1);
+    assert(count({a, a + 10}) == 2);
+    assert(count({a, a + 1, a + 2}) == 3);
+    assert(count(std::initializer_list<Sink>{a[0], a[1], a[2], a[3]}) == 4);
+  }
+#else
+  {
     Sink a[10];
+
     assert(count({a}) == 10);
-    assert(count({a, a+10}) == 10);
-    assert(countn<10>({a}) == 10);
-    return true;
+    assert(count({a, a + 10}) == 10);
+    assert(count_n<10>({a}) == 10);
+  }
+#endif
+
+  return true;
+}
+
+// Test P2447R4 "Annex C examples"
+
+constexpr int three(std::span<void* const> sp) { return sp.size(); }
+
+constexpr int four(std::span<const std::any> sp) { return sp.size(); }
+
+bool test_P2447R4_annex_c_examples() {
+  // 1. Overload resolution is affected
+  // --> tested in "initializer_list.verify.cpp"
+
+  // 2. The `initializer_list` ctor has high precedence
+  // --> tested in "initializer_list.verify.cpp"
+
+  // 3. Implicit two-argument construction with a highly convertible value_type
----------------
mordante wrote:

nice! thanks for referring to the other test too!

https://github.com/llvm/llvm-project/pull/78157


More information about the cfe-commits mailing list