diff --git a/libcxx/docs/Status/Cxx20Papers.csv b/libcxx/docs/Status/Cxx20Papers.csv
--- a/libcxx/docs/Status/Cxx20Papers.csv
+++ b/libcxx/docs/Status/Cxx20Papers.csv
@@ -135,7 +135,7 @@
 "","","","","",""
 "`P0883 <https://wg21.link/P0883>`__","LWG","Fixing Atomic Initialization","Belfast","|Complete| [#note-P0883]_","13.0"
 "`P1391 <https://wg21.link/P1391>`__","LWG","Range constructor for std::string_view","Belfast","* *",""
-"`P1394 <https://wg21.link/P1394>`__","LWG","Range constructor for std::span","Belfast","* *",""
+"`P1394 <https://wg21.link/P1394>`__","LWG","Range constructor for std::span","Belfast","|Complete|","14.0"
 "`P1456 <https://wg21.link/P1456>`__","LWG","Move-only views","Belfast","* *",""
 "`P1622 <https://wg21.link/P1622>`__","LWG","Mandating the Standard Library: Clause 32 - Thread support library","Belfast","* *",""
 "`P1645 <https://wg21.link/P1645>`__","LWG","constexpr for numeric algorithms","Belfast","|Complete|","12.0"
diff --git a/libcxx/include/span b/libcxx/include/span
--- a/libcxx/include/span
+++ b/libcxx/include/span
@@ -56,18 +56,18 @@
 
     // [span.cons], span constructors, copy, assignment, and destructor
     constexpr span() noexcept;
-    constexpr explicit(Extent != dynamic_extent) span(pointer ptr, size_type count);
-    constexpr explicit(Extent != dynamic_extent) span(pointer firstElem, pointer lastElem);
+    template <class It>
+    constexpr explicit(Extent != dynamic_extent) span(It first, size_type count);
+    template <class It, class End>
+    constexpr explicit(Extent != dynamic_extent) span(It first, End last);
     template <size_t N>
         constexpr span(element_type (&arr)[N]) noexcept;
     template <size_t N>
         constexpr span(array<value_type, N>& arr) noexcept;
     template <size_t N>
         constexpr span(const array<value_type, N>& arr) noexcept;
-    template <class Container>
-        constexpr explicit(Extent != dynamic_extent) span(Container& cont);
-    template <class Container>
-        constexpr explicit(Extent != dynamic_extent) span(const Container& cont);
+    template<class R>
+      constexpr explicit(extent != dynamic_extent) span(R&& r);
     constexpr span(const span& other) noexcept = default;
     template <class OtherElementType, size_t OtherExtent>
         constexpr explicit(Extent != dynamic_extent) span(const span<OtherElementType, OtherExtent>& s) noexcept;
@@ -108,6 +108,9 @@
     size_type size_;  // exposition only
 };
 
+template<class It, class EndOrSize>
+    span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;
+
 template<class T, size_t N>
     span(T (&)[N]) -> span<T, N>;
 
@@ -117,11 +120,8 @@
 template<class T, size_t N>
     span(const array<T, N>&) -> span<const T, N>;
 
-template<class Container>
-    span(Container&) -> span<typename Container::value_type>;
-
-template<class Container>
-    span(const Container&) -> span<const typename Container::value_type>;
+template<class R>
+    span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;
 
 } // namespace std
 
@@ -129,7 +129,10 @@
 
 #include <__config>
 #include <__debug>
+#include <__iterator/concepts.h>
 #include <__iterator/wrap_iter.h>
+#include <__ranges/concepts.h>
+#include <__ranges/data.h>
 #include <__ranges/enable_borrowed_range.h>
 #include <__ranges/enable_view.h>
 #include <array>        // for array
@@ -155,22 +158,16 @@
 
 
 template <class _Tp>
-struct __is_span_impl : public false_type {};
+struct __is_std_array : false_type {};
 
-template <class _Tp, size_t _Extent>
-struct __is_span_impl<span<_Tp, _Extent>> : public true_type {};
-
-template <class _Tp>
-struct __is_span : public __is_span_impl<remove_cv_t<_Tp>> {};
+template <class _Tp, size_t _Sz>
+struct __is_std_array<array<_Tp, _Sz>> : true_type {};
 
 template <class _Tp>
-struct __is_std_array_impl : public false_type {};
+struct __is_std_span : false_type {};
 
 template <class _Tp, size_t _Sz>
-struct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {};
-
-template <class _Tp>
-struct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {};
+struct __is_std_span<span<_Tp, _Sz>> : true_type {};
 
 template <class _Tp, class _ElementType, class = void>
 struct __is_span_compatible_container : public false_type {};
@@ -179,9 +176,9 @@
 struct __is_span_compatible_container<_Tp, _ElementType,
         void_t<
         // is not a specialization of span
-            enable_if_t<!__is_span<_Tp>::value, nullptr_t>,
+            enable_if_t<!__is_std_span<remove_cvref_t<_Tp>>::value, nullptr_t>,
         // is not a specialization of array
-            enable_if_t<!__is_std_array<_Tp>::value, nullptr_t>,
+            enable_if_t<!__is_std_array<remove_cvref_t<_Tp>>::value, nullptr_t>,
         // is_array_v<Container> is false,
             enable_if_t<!is_array_v<_Tp>, nullptr_t>,
         // data(cont) and size(cont) are well formed
@@ -195,6 +192,17 @@
         >>
     : public true_type {};
 
+#if _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_RANGES)
+template <class _Range, class _ElementType>
+concept __is_span_compatible_range =
+  ranges::contiguous_range<_Range> &&
+  ranges::sized_range<_Range> &&
+  (ranges::borrowed_range<_Range> || is_const_v<_ElementType>) &&
+  !__is_std_span<remove_cvref_t<_Range>>::value  &&
+  !__is_std_array<remove_cvref_t<_Range>>::value &&
+  !is_array_v<remove_cvref_t<_Range>> &&
+  is_convertible_v<remove_reference_t<ranges::range_reference_t<_Range>> (*)[], _ElementType(*)[]>;
+#endif
 
 template <typename _Tp, size_t _Extent>
 class _LIBCPP_TEMPLATE_VIS span {
@@ -224,10 +232,25 @@
     constexpr span           (const span&) noexcept = default;
     constexpr span& operator=(const span&) noexcept = default;
 
-    _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 explicit span(pointer __f, pointer __l) : __data{__f}
-        { (void)__l;     _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); }
+    template <class _It, enable_if_t<contiguous_iterator<_It> &&
+              is_convertible_v<remove_reference_t<iter_reference_t<_It>>(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(_It __first,  size_type __count) : __data{_VSTD::to_address(__first)}
+        {
+          (void)__count;
+          _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (iterator, len)");
+        }
+
+    template <class _It, class _End, enable_if_t<
+              is_convertible_v<remove_reference_t<iter_reference_t<_It>>(*)[], element_type (*)[]> &&
+              contiguous_iterator<_It> &&
+              sized_sentinel_for<_End, _It> &&
+              !is_convertible_v<_End, size_t>, nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(_It __first, _End __last) : __data{_VSTD::to_address(__first)}
+       {
+         (void) __last;
+         _LIBCPP_ASSERT(__first <= __last, "invalid range in span's constructor (iterator, sentinel)");
+         _LIBCPP_ASSERT(last - first == _Extent, "invalid range in span's constructor (iterator sentinel): last - first != extent");
+       }
 
     _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent])          noexcept : __data{__arr} {}
 
@@ -241,21 +264,12 @@
     _LIBCPP_INLINE_VISIBILITY
     constexpr span(const array<_OtherElementType, _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)");
-        }
+#if _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_RANGES)
+    template <__is_span_compatible_range<element_type> _Range>
+    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(_Range&& __r) : __data{ranges::data(__r)} {
+      _LIBCPP_ASSERT(ranges::size(__r) == _Extent, "size mismatch in span's constructor (range)");
+    }
+#endif
 
     template <class _OtherElementType>
     _LIBCPP_INLINE_VISIBILITY
@@ -402,8 +416,17 @@
     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}, __size{__count} {}
-    _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<size_t>(distance(__f, __l))} {}
+    template <class _It, enable_if_t<contiguous_iterator<_It> &&
+              is_convertible_v<remove_reference_t<iter_reference_t<_It>>(*)[], element_type (*)[]>, nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY constexpr span(_It __first,  size_type __count) : __data{_VSTD::to_address(__first)}, __size{__count} {}
+
+    template <class _It, class _End, enable_if_t<
+              is_convertible_v<remove_reference_t<iter_reference_t<_It>>(*)[], element_type (*)[]> &&
+              contiguous_iterator<_It> &&
+              sized_sentinel_for<_End, _It> &&
+              !is_convertible_v<_End, size_t>, nullptr_t> = nullptr>
+    _LIBCPP_INLINE_VISIBILITY constexpr span(_It __first, _End __last)
+      : __data{_VSTD::to_address(__first)}, __size(static_cast<size_t>(_VSTD::distance(__first, __last))) {}
 
     template <size_t _Sz>
     _LIBCPP_INLINE_VISIBILITY
@@ -419,18 +442,11 @@
     _LIBCPP_INLINE_VISIBILITY
     constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
 
-    template <class _Container>
-    _LIBCPP_INLINE_VISIBILITY
-        constexpr span(      _Container& __c,
-            enable_if_t<__is_span_compatible_container<_Container, _Tp>::value, nullptr_t> = nullptr)
-        : __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {}
-
-    template <class _Container>
-    _LIBCPP_INLINE_VISIBILITY
-        constexpr span(const _Container& __c,
-            enable_if_t<__is_span_compatible_container<const _Container, _Tp>::value, nullptr_t> = nullptr)
-        : __data{_VSTD::data(__c)}, __size{(size_type) _VSTD::size(__c)} {}
-
+#if _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_RANGES)
+    template <__is_span_compatible_range<element_type> _Range>
+    _LIBCPP_INLINE_VISIBILITY constexpr explicit span(_Range&& __r) : __data{ranges::data(__r)}, __size{ranges::size(__r)} {
+    }
+#endif
 
     template <class _OtherElementType, size_t _OtherExtent>
     _LIBCPP_INLINE_VISIBILITY
@@ -557,6 +573,9 @@
 { return __s.__as_writable_bytes(); }
 
 //  Deduction guides
+template<contiguous_iterator _It, class _EndOrSize>
+    span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;
+
 template<class _Tp, size_t _Sz>
     span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
 
@@ -566,11 +585,10 @@
 template<class _Tp, size_t _Sz>
     span(const array<_Tp, _Sz>&) -> span<const _Tp, _Sz>;
 
-template<class _Container>
-    span(_Container&) -> span<typename _Container::value_type>;
-
-template<class _Container>
-    span(const _Container&) -> span<const typename _Container::value_type>;
+#if _LIBCPP_STD_VER > 20 && !defined(_LIBCPP_HAS_NO_RANGES)
+template<ranges::contiguous_range _Range>
+    span(_Range&&) -> span<remove_reference_t<ranges::range_reference_t<_Range>>>;
+#endif
 
 #endif // _LIBCPP_STD_VER > 17
 
diff --git a/libcxx/test/std/containers/views/span.cons/container.fail.cpp b/libcxx/test/std/containers/views/span.cons/container.fail.cpp
deleted file mode 100644
--- a/libcxx/test/std/containers/views/span.cons/container.fail.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-// -*- C++ -*-
-//===------------------------------ span ---------------------------------===//
-//
-// 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
-
-// <span>
-
-//  template<class Container>
-//     constexpr span(Container& cont);
-//   template<class Container>
-//     constexpr span(const Container& cont);
-//
-// Remarks: These constructors shall not participate in overload resolution unless:
-//   — extent == dynamic_extent,
-//   — Container is not a specialization of span,
-//   — Container is not a specialization of array,
-//   — is_array_v<Container> is false,
-//   — data(cont) and size(cont) are both well-formed, and
-//   — remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[].
-//
-
-#include <span>
-#include <cassert>
-#include <deque>
-#include <forward_list>
-#include <list>
-#include <vector>
-
-#include "test_macros.h"
-
-//  Look ma - I'm a container!
-template <typename T>
-struct IsAContainer {
-    constexpr IsAContainer() : v_{} {}
-    constexpr size_t size() const {return 1;}
-    constexpr       T *data() {return &v_;}
-    constexpr const T *data() const {return &v_;}
-
-    constexpr const T *getV() const {return &v_;} // for checking
-    T v_;
-};
-
-template <typename T>
-struct NotAContainerNoData {
-    size_t size() const {return 0;}
-};
-
-template <typename T>
-struct NotAContainerNoSize {
-    const T *data() const {return nullptr;}
-};
-
-template <typename T>
-struct NotAContainerPrivate {
-private:
-    size_t size() const {return 0;}
-    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**)
-{
-
-//  Making non-const spans from const sources (a temporary binds to `const &`)
-    {
-    std::span<int>    s1{IsAContainer<int>()};          // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<int>    s3{std::vector<int>()};           // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    }
-
-//  Missing size and/or data
-    {
-    std::span<const int>    s1{NotAContainerNoData<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const int>    s3{NotAContainerNoSize<int>()};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const int>    s5{NotAContainerPrivate<int>()};  // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-
-//  Again with the standard containers
-    std::span<const int>    s11{std::deque<int>()};           // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const int>    s13{std::list<int>()};            // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const int>    s15{std::forward_list<int>()};    // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    }
-
-//  Not the same type
-    {
-    IsAContainer<int> c;
-    std::span<float>    s1{c};   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
-    }
-
-//  CV wrong
-    {
-    IsAContainer<const          int> c;
-    IsAContainer<const volatile int> cv;
-    IsAContainer<      volatile int> v;
-
-    std::span<               int> s1{c};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s2{v};    // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s3{cv};   // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<const          int> s4{v};    // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const          int> s5{cv};   // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<      volatile int> s6{c};    // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    std::span<      volatile int> s7{cv};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    }
-
-// explicit constructor necessary
-    {
-    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
deleted file mode 100644
--- a/libcxx/test/std/containers/views/span.cons/container.pass.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-// -*- C++ -*-
-//===------------------------------ span ---------------------------------===//
-//
-// 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
-
-// <span>
-
-//  template<class Container>
-//     constexpr span(Container& cont);
-//   template<class Container>
-//     constexpr span(const Container& cont);
-//
-// Remarks: These constructors shall not participate in overload resolution unless:
-//   — extent == dynamic_extent,
-//   — Container is not a specialization of span,
-//   — Container is not a specialization of array,
-//   — is_array_v<Container> is false,
-//   — data(cont) and size(cont) are both well-formed, and
-//   — remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[].
-//
-
-
-#include <span>
-#include <cassert>
-#include <string>
-#include <vector>
-
-#include "test_macros.h"
-
-//  Look ma - I'm a container!
-template <typename T>
-struct IsAContainer {
-    constexpr IsAContainer() : v_{} {}
-    constexpr size_t size() const {return 1;}
-    constexpr       T *data() {return &v_;}
-    constexpr const T *data() const {return &v_;}
-    constexpr       T *begin() {return &v_;}
-    constexpr const T *begin() const {return &v_;}
-    constexpr       T *end() {return &v_ + 1;}
-    constexpr const T *end() const {return &v_ + 1;}
-
-    constexpr T const *getV() const {return &v_;} // for checking
-    T v_;
-};
-
-
-void checkCV()
-{
-    std::vector<int> v  = {1,2,3};
-
-//  Types the same
-    {
-    std::span<               int> s1{v};    // a span<               int> pointing at int.
-    }
-
-//  types different
-    {
-    std::span<const          int> s1{v};    // a span<const          int> pointing at int.
-    std::span<      volatile int> s2{v};    // a span<      volatile int> pointing at int.
-    std::span<      volatile int> s3{v};    // a span<      volatile int> pointing at const int.
-    std::span<const volatile int> s4{v};    // a span<const volatile int> pointing at int.
-    }
-
-//  Constructing a const view from a temporary
-    {
-    std::span<const int>    s1{IsAContainer<int>()};
-    std::span<const int>    s3{std::vector<int>()};
-    (void) s1;
-    (void) s3;
-    }
-}
-
-
-template <typename T>
-constexpr bool testConstexprSpan()
-{
-    constexpr IsAContainer<const T> val{};
-    std::span<const T> s1{val};
-    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};
-    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);
-}
-
-struct A{};
-
-int main(int, char**)
-{
-    static_assert(testConstexprSpan<int>(),    "");
-    static_assert(testConstexprSpan<long>(),   "");
-    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/deduct.pass.cpp b/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
--- a/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
+++ b/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp
@@ -1,4 +1,3 @@
-// -*- C++ -*-
 //===------------------------------ span ---------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
@@ -7,9 +6,13 @@
 //
 //===---------------------------------------------------------------------===//
 // UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
 
 // <span>
 
+//   template<class It, class EndOrSize>
+//     span(It, EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;
+//
 //   template<class T, size_t N>
 //     span(T (&)[N]) -> span<T, N>;
 //
@@ -19,12 +22,8 @@
 //   template<class T, size_t N>
 //     span(const array<T, N>&) -> span<const T, N>;
 //
-//   template<class Container>
-//     span(Container&) -> span<typename Container::value_type>;
-//
-//   template<class Container>
-//     span(const Container&) -> span<const typename Container::value_type>;
-
+//   template<class R>
+//     span(R&&) -> span<remove_reference_t<ranges::range_reference_t<R>>>;
 
 
 #include <span>
@@ -33,12 +32,28 @@
 #include <memory>
 #include <string>
 
+#include "simple_range.h"
 #include "test_macros.h"
 
-int main(int, char**)
-{
+void test_iterator_sentinel() {
+  int arr[] = {1, 2, 3};
+  {
+  std::span s{std::begin(arr), std::end(arr)};
+  ASSERT_SAME_TYPE(decltype(s), std::span<int>);
+  assert(s.size() == std::size(arr));
+  assert(s.data() == std::data(arr));
+  }
+  {
+  std::span s{std::begin(arr), 3};
+  ASSERT_SAME_TYPE(decltype(s), std::span<int>);
+  assert(s.size() == std::size(arr));
+  assert(s.data() == std::data(arr));
+  }
+}
+
+void test_c_array() {
     {
-    int arr[] = {1,2,3};
+    int arr[] = {1, 2, 3};
     std::span s{arr};
     ASSERT_SAME_TYPE(decltype(s), std::span<int, 3>);
     assert(s.size() == std::size(arr));
@@ -52,7 +67,9 @@
     assert(s.size() == std::size(arr));
     assert(s.data() == std::data(arr));
     }
+}
 
+void test_std_array() {
     {
     std::array<double, 4> arr = {1.0, 2.0, 3.0, 4.0};
     std::span s{arr};
@@ -68,7 +85,9 @@
     assert(s.size() == arr.size());
     assert(s.data() == arr.data());
     }
+}
 
+void test_range_std_container() {
     {
     std::string str{"ABCDE"};
     std::span s{str};
@@ -84,6 +103,33 @@
     assert(s.size() == str.size());
     assert(s.data() == str.data());
     }
+}
+
+void test_range_user_defined() {
+    {
+    SimpleRange<int, 3> r{};
+    std::span s{r};
+    ASSERT_SAME_TYPE(decltype(s), std::span<int>);
+    assert(s.size() == r.size());
+    assert(s.data() == r.data());
+    }
+
+    {
+    const SimpleRange<int, 3> r{};
+    std::span s{r};
+    ASSERT_SAME_TYPE(decltype(s), std::span<const int>);
+    assert(s.size() == r.size());
+    assert(s.data() == r.data());
+    }
+}
+
+int main(int, char**)
+{
+  test_iterator_sentinel();
+  test_c_array();
+  test_std_array();
+  test_range_std_container();
+  test_range_user_defined();
 
   return 0;
 }
diff --git a/libcxx/test/std/containers/views/span.cons/iterator_iterator.compile.pass.cpp b/libcxx/test/std/containers/views/span.cons/iterator_iterator.compile.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/iterator_iterator.compile.pass.cpp
@@ -0,0 +1,46 @@
+//===------------------------------ span ---------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// <span>
+
+// template <class It, class End>
+// constexpr explicit(Extent != dynamic_extent) span(It first, End last);
+// Requires: [first, last) shall be a valid range.
+//   If extent is not equal to dynamic_extent, then last - first shall be equal to extent.
+//
+
+#include <span>
+
+#include <type_traits>
+
+template <size_t Extent>
+void test_cv() {
+  static_assert( std::is_constructible_v<std::span<int, Extent>, int*, int*>);
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, const int*, const int*>);
+  static_assert(!std::is_constructible_v<std::span<int, Extent>, volatile int*, volatile int*>);
+  static_assert( std::is_constructible_v<std::span<const int, Extent>, int*, int*>);
+  static_assert( std::is_constructible_v<std::span<const int, Extent>, const int*, const int*>);
+  static_assert(!std::is_constructible_v<std::span<const int, Extent>, volatile int*, volatile int*>);
+  static_assert( std::is_constructible_v<std::span<volatile int, Extent>, int*, int*>);
+  static_assert(!std::is_constructible_v<std::span<volatile int, Extent>, const int*, const int*>);
+  static_assert( std::is_constructible_v<std::span<volatile int, Extent>, volatile int*, volatile int*>);
+}
+
+int main(int, char**)
+{
+  // Types wrong
+  static_assert(!std::is_constructible_v<std::span<int>, int*, float*>);
+  static_assert(!std::is_constructible_v<std::span<int, 3>, int*, float*>);
+
+  test_cv<std::dynamic_extent>();
+  test_cv<3>();
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/span.cons/iterator_iterator.fail.cpp b/libcxx/test/std/containers/views/span.cons/iterator_iterator.fail.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/iterator_iterator.fail.cpp
@@ -0,0 +1,35 @@
+//===------------------------------ span ---------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// <span>
+
+// template <class It, class End>
+// constexpr explicit(Extent != dynamic_extent) span(It first, End last);
+// Requires: [first, last) shall be a valid range.
+//   If extent is not equal to dynamic_extent, then last - first shall be equal to extent.
+//
+
+#include <span>
+
+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**)
+{
+    int arr[] = {1, 2, 3};
+    // explicit constructor necessary
+    {
+    createImplicitSpan<int, 1>(std::begin(arr), std::next(std::begin(arr)));
+    }
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/span.cons/iterator_iterator.pass.cpp b/libcxx/test/std/containers/views/span.cons/iterator_iterator.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/iterator_iterator.pass.cpp
@@ -0,0 +1,95 @@
+//===------------------------------ span ---------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// <span>
+
+// template <class It, class End>
+// constexpr explicit(Extent != dynamic_extent) span(It first, End last);
+// Requires: [first, last) shall be a valid range.
+//   If extent is not equal to dynamic_extent, then last - first shall be equal to extent.
+//
+
+#include <span>
+#include <cassert>
+
+void checkCV()
+{
+                   int   arr[] = {1,2,3};
+    const          int  carr[] = {4,5,6};
+          volatile int  varr[] = {7,8,9};
+    const volatile int cvarr[] = {1,3,5};
+
+//  Types the same (dynamic sized)
+    {
+    std::span<               int> s1{std::begin(arr), std::end(arr)}; // a span<               int> pointing at int.
+    std::span<const          int> s2{std::begin(carr), std::end(carr)}; // a span<const          int> pointing at const int.
+    std::span<      volatile int> s3{std::begin(varr), std::end(varr)}; // a span<      volatile int> pointing at volatile int.
+    std::span<const volatile int> s4{std::begin(cvarr), std::end(cvarr)}; // a span<const volatile int> pointing at const volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
+    }
+
+//  Types the same (static sized)
+    {
+    std::span<               int,3> s1{std::begin(arr), std::end(arr)};     // a span<               int> pointing at int.
+    std::span<const          int,3> s2{std::begin(carr), std::end(carr)};    // a span<const          int> pointing at const int.
+    std::span<      volatile int,3> s3{std::begin(varr), std::end(varr)};   // a span<      volatile int> pointing at volatile int.
+    std::span<const volatile int,3> s4{std::begin(cvarr), std::end(cvarr)}; // a span<const volatile int> pointing at const volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
+    }
+
+
+//  Types different (dynamic sized)
+    {
+    std::span<const          int> s1{std::begin(arr), std::end(arr)};       // a span<const          int> pointing at int.
+    std::span<      volatile int> s2{std::begin(arr), std::end(arr)};       // a span<      volatile int> pointing at int.
+    std::span<      volatile int> s3{std::begin(arr), std::end(arr)};       // a span<      volatile int> pointing at const int.
+    std::span<const volatile int> s4{std::begin(arr), std::end(arr)};       // a span<const volatile int> pointing at int.
+    std::span<const volatile int> s5{std::begin(carr), std::end(carr)};       // a span<const volatile int> pointing at const int.
+    std::span<const volatile int> s6{std::begin(varr), std::end(varr)};       // a span<const volatile int> pointing at volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
+    }
+
+//  Types different (static sized)
+    {
+    std::span<const          int,3> s1{std::begin(arr),  std::end(arr)}; // a span<const          int> pointing at int.
+    std::span<      volatile int,3> s2{std::begin(arr),  std::end(arr)}; // a span<      volatile int> pointing at int.
+    std::span<      volatile int,3> s3{std::begin(arr),  std::end(arr)}; // a span<      volatile int> pointing at const int.
+    std::span<const volatile int,3> s4{std::begin(arr),  std::end(arr)}; // a span<const volatile int> pointing at int.
+    std::span<const volatile int,3> s5{std::begin(carr), std::cend(carr)}; // a span<const volatile int> pointing at const int.
+    std::span<const volatile int,3> s6{std::begin(varr), std::end(varr)}; // a span<const volatile int> pointing at volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
+    }
+}
+
+template <class T>
+constexpr bool test()
+{
+    T val[2] = {};
+    auto s1 = std::span<T>(std::begin(val), std::end(val));
+    auto s2 = std::span<T, 2>(std::begin(val), std::end(val));
+    assert(s1.data() == std::data(val) && s1.size() == std::size(val));
+    assert(s2.data() == std::data(val) && s2.size() == std::size(val));
+    return true;
+}
+
+struct A{};
+
+int main(int, char**)
+{
+    static_assert(test<int>());
+    assert(test<int>());
+
+    static_assert(test<A>());
+    assert(test<A>());
+
+    checkCV();
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/span.cons/iterator_len.fail.cpp b/libcxx/test/std/containers/views/span.cons/iterator_len.fail.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/iterator_len.fail.cpp
@@ -0,0 +1,74 @@
+//===------------------------------ span ---------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// <span>
+
+// template <class It>
+// constexpr explicit(Extent != dynamic_extent) span(It first, size_type count);
+//  If extent is not equal to dynamic_extent, then count shall be equal to extent.
+//
+
+#include <span>
+#include <cassert>
+#include <string>
+
+#include "test_macros.h"
+
+
+               int   arr[] = {1,2,3};
+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
+//  std::span<int, 2>   s1(arr, 3);
+
+//  Type wrong
+    {
+    std::span<float>    s1(std::begin(arr), 3);   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
+    std::span<float, 3> s2(std::begin(arr), 3);   // expected-error {{no matching constructor for initialization of 'std::span<float, 3>'}}
+    }
+
+//  CV wrong (dynamically sized)
+    {
+    std::span<               int> s1{std::begin(carr), 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s2{std::begin(varr), 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<               int> s3{std::begin(cvarr), 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<const          int> s4{std::begin(varr), 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+    std::span<const          int> s5{std::begin(cvarr), 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+    std::span<      volatile int> s6{std::begin(carr), 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    std::span<      volatile int> s7{std::begin(cvarr), 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+    }
+
+//  CV wrong (statically sized)
+    {
+    std::span<               int,3> s1{std::begin(carr), 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
+    std::span<               int,3> s2{std::begin(varr), 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
+    std::span<               int,3> s3{std::begin(cvarr), 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
+    std::span<const          int,3> s4{std::begin(varr), 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
+    std::span<const          int,3> s5{std::begin(cvarr), 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
+    std::span<      volatile int,3> s6{std::begin(carr), 3};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
+    std::span<      volatile int,3> s7{std::begin(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/iterator_len.pass.cpp b/libcxx/test/std/containers/views/span.cons/iterator_len.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/iterator_len.pass.cpp
@@ -0,0 +1,98 @@
+//===------------------------------ span ---------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// <span>
+
+// template <class It>
+// constexpr explicit(Extent != dynamic_extent) span(It first, size_type count);
+//  If extent is not equal to dynamic_extent, then count shall be equal to extent.
+//
+
+
+#include <span>
+#include <cassert>
+
+#include "test_macros.h"
+
+void checkCV()
+{
+                   int   arr[] = {1,2,3};
+    const          int  carr[] = {4,5,6};
+          volatile int  varr[] = {7,8,9};
+    const volatile int cvarr[] = {1,3,5};
+
+//  Types the same (dynamic sized)
+    {
+    std::span<               int> s1{std::begin(arr), 3}; // a span<               int> pointing at int.
+    std::span<const          int> s2{std::begin(carr), 3}; // a span<const          int> pointing at const int.
+    std::span<      volatile int> s3{std::begin(varr), 3}; // a span<      volatile int> pointing at volatile int.
+    std::span<const volatile int> s4{std::begin(cvarr), 3}; // a span<const volatile int> pointing at const volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
+    }
+
+//  Types the same (static sized)
+    {
+    std::span<               int,3> s1{std::begin(arr), 3};   // a span<               int> pointing at int.
+    std::span<const          int,3> s2{std::begin(carr), 3};   // a span<const          int> pointing at const int.
+    std::span<      volatile int,3> s3{std::begin(varr), 3};   // a span<      volatile int> pointing at volatile int.
+    std::span<const volatile int,3> s4{std::begin(cvarr), 3};   // a span<const volatile int> pointing at const volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
+    }
+
+
+//  types different (dynamic sized)
+    {
+    std::span<const          int> s1{std::begin(arr), 3};      // a span<const          int> pointing at int.
+    std::span<      volatile int> s2{std::begin(arr), 3};      // a span<      volatile int> pointing at int.
+    std::span<      volatile int> s3{std::begin(arr), 3};      // a span<      volatile int> pointing at const int.
+    std::span<const volatile int> s4{std::begin(arr), 3};      // a span<const volatile int> pointing at int.
+    std::span<const volatile int> s5{std::begin(carr), 3};      // a span<const volatile int> pointing at const int.
+    std::span<const volatile int> s6{std::begin(varr), 3};      // a span<const volatile int> pointing at volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
+    }
+
+//  types different (static sized)
+    {
+    std::span<const          int,3> s1{std::begin(arr), 3};    // a span<const          int> pointing at int.
+    std::span<      volatile int,3> s2{std::begin(arr), 3};    // a span<      volatile int> pointing at int.
+    std::span<      volatile int,3> s3{std::begin(arr), 3};    // a span<      volatile int> pointing at const int.
+    std::span<const volatile int,3> s4{std::begin(arr), 3};    // a span<const volatile int> pointing at int.
+    std::span<const volatile int,3> s5{std::begin(carr), 3};    // a span<const volatile int> pointing at const int.
+    std::span<const volatile int,3> s6{std::begin(varr), 3};    // a span<const volatile int> pointing at volatile int.
+    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
+    }
+}
+
+
+template <class T>
+constexpr bool test()
+{
+    T val[2] = {};
+    auto s1 = std::span<T>(val, 2);
+    auto s2 = std::span<T, 2>(val, 2);
+    assert(s1.data() == std::data(val) && s1.size() == std::size(val));
+    assert(s2.data() == std::data(val) && s2.size() == std::size(val));
+    return true;
+}
+
+struct A{};
+
+int main(int, char**)
+{
+    static_assert(test<int>());
+    assert(test<int>());
+
+    static_assert(test<A>());
+    assert(test<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
deleted file mode 100644
--- a/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-// -*- C++ -*-
-//===------------------------------ span ---------------------------------===//
-//
-// 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
-
-// <span>
-
-// constexpr span(pointer ptr, size_type count);
-// Requires: [ptr, ptr + count) shall be a valid range.
-//  If extent is not equal to dynamic_extent, then count shall be equal to extent.
-//
-
-#include <span>
-#include <cassert>
-#include <string>
-
-#include "test_macros.h"
-
-
-               int   arr[] = {1,2,3};
-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
-//  std::span<int, 2>   s1(arr, 3);
-
-//  Type wrong
-    {
-    std::span<float>    s1(arr, 3);   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
-    std::span<float, 3> s2(arr, 3);   // expected-error {{no matching constructor for initialization of 'std::span<float, 3>'}}
-    }
-
-//  CV wrong (dynamically sized)
-    {
-    std::span<               int> s1{ carr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s2{ varr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s3{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<const          int> s4{ varr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const          int> s5{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<      volatile int> s6{ carr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    std::span<      volatile int> s7{cvarr, 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    }
-
-//  CV wrong (statically sized)
-    {
-    std::span<               int,3> s1{ carr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<               int,3> s2{ varr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<               int,3> s3{cvarr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<const          int,3> s4{ varr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
-    std::span<const          int,3> s5{cvarr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
-    std::span<      volatile int,3> s6{ carr, 3};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
-    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_len.pass.cpp b/libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp
deleted file mode 100644
--- a/libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-// -*- C++ -*-
-//===------------------------------ span ---------------------------------===//
-//
-// 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
-
-// <span>
-
-// constexpr span(pointer ptr, size_type count);
-// Requires: [ptr, ptr + count) shall be a valid range.
-//  If extent is not equal to dynamic_extent, then count shall be equal to extent.
-//
-
-#include <span>
-#include <cassert>
-#include <string>
-
-#include "test_macros.h"
-
-void checkCV()
-{
-                   int   arr[] = {1,2,3};
-    const          int  carr[] = {4,5,6};
-          volatile int  varr[] = {7,8,9};
-    const volatile int cvarr[] = {1,3,5};
-
-//  Types the same (dynamic sized)
-    {
-    std::span<               int> s1{  arr, 3}; // a span<               int> pointing at int.
-    std::span<const          int> s2{ carr, 3}; // a span<const          int> pointing at const int.
-    std::span<      volatile int> s3{ varr, 3}; // a span<      volatile int> pointing at volatile int.
-    std::span<const volatile int> s4{cvarr, 3}; // a span<const volatile int> pointing at const volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
-    }
-
-//  Types the same (static sized)
-    {
-    std::span<               int,3> s1{  arr, 3};   // a span<               int> pointing at int.
-    std::span<const          int,3> s2{ carr, 3};   // a span<const          int> pointing at const int.
-    std::span<      volatile int,3> s3{ varr, 3};   // a span<      volatile int> pointing at volatile int.
-    std::span<const volatile int,3> s4{cvarr, 3};   // a span<const volatile int> pointing at const volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
-    }
-
-
-//  types different (dynamic sized)
-    {
-    std::span<const          int> s1{ arr, 3};      // a span<const          int> pointing at int.
-    std::span<      volatile int> s2{ arr, 3};      // a span<      volatile int> pointing at int.
-    std::span<      volatile int> s3{ arr, 3};      // a span<      volatile int> pointing at const int.
-    std::span<const volatile int> s4{ arr, 3};      // a span<const volatile int> pointing at int.
-    std::span<const volatile int> s5{carr, 3};      // a span<const volatile int> pointing at const int.
-    std::span<const volatile int> s6{varr, 3};      // a span<const volatile int> pointing at volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
-    }
-
-//  types different (static sized)
-    {
-    std::span<const          int,3> s1{ arr, 3};    // a span<const          int> pointing at int.
-    std::span<      volatile int,3> s2{ arr, 3};    // a span<      volatile int> pointing at int.
-    std::span<      volatile int,3> s3{ arr, 3};    // a span<      volatile int> pointing at const int.
-    std::span<const volatile int,3> s4{ arr, 3};    // a span<const volatile int> pointing at int.
-    std::span<const volatile int,3> s5{carr, 3};    // a span<const volatile int> pointing at const int.
-    std::span<const volatile int,3> s6{varr, 3};    // a span<const volatile int> pointing at volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
-    }
-}
-
-
-template <typename T>
-constexpr bool testConstexprSpan()
-{
-    constexpr T val[2] = {};
-    std::span<const T>   s1{val, 2};
-    std::span<const T,2> s2{val, 2};
-    return
-        s1.data() == &val[0] && s1.size() == 2
-    &&  s2.data() == &val[0] && s2.size() == 2;
-}
-
-
-template <typename T>
-void testRuntimeSpan()
-{
-    T val[2] = {};
-    std::span<T>   s1{val, 2};
-    std::span<T,2> s2{val, 2};
-    assert(s1.data() == &val[0] && s1.size() == 2);
-    assert(s2.data() == &val[0] && s2.size() == 2);
-}
-
-struct A{};
-
-int main(int, char**)
-{
-    static_assert(testConstexprSpan<int>(),    "");
-    static_assert(testConstexprSpan<long>(),   "");
-    static_assert(testConstexprSpan<double>(), "");
-    static_assert(testConstexprSpan<A>(),      "");
-
-    testRuntimeSpan<int>();
-    testRuntimeSpan<long>();
-    testRuntimeSpan<double>();
-    testRuntimeSpan<std::string>();
-    testRuntimeSpan<A>();
-
-    checkCV();
-
-  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
deleted file mode 100644
--- a/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-// -*- C++ -*-
-//===------------------------------ span ---------------------------------===//
-//
-// 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
-
-// <span>
-
-// constexpr span(pointer first, pointer last);
-// Requires: [first, last) shall be a valid range.
-//   If extent is not equal to dynamic_extent, then last - first shall be equal to extent.
-//
-
-#include <span>
-#include <cassert>
-#include <string>
-
-#include "test_macros.h"
-
-
-               int   arr[] = {1,2,3};
-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
-//  std::span<int, 2>   s1(arr, arr + 3);
-
-//  Type wrong
-    {
-    std::span<float>    s1(arr, arr + 3);   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
-    std::span<float, 3> s2(arr, arr + 3);   // expected-error {{no matching constructor for initialization of 'std::span<float, 3>'}}
-    }
-
-//  CV wrong (dynamically sized)
-    {
-    std::span<               int> s1{ carr,  carr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s2{ varr,  varr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<               int> s3{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
-    std::span<const          int> s4{ varr,  varr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<const          int> s5{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
-    std::span<      volatile int> s6{ carr,  carr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    std::span<      volatile int> s7{cvarr, cvarr + 3}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
-    }
-
-//  CV wrong (statically sized)
-    {
-    std::span<               int,3> s1{ carr,  carr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<               int,3> s2{ varr,  varr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<               int,3> s3{cvarr, cvarr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}}
-    std::span<const          int,3> s4{ varr,  varr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
-    std::span<const          int,3> s5{cvarr, cvarr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}}
-    std::span<      volatile int,3> s6{ carr,  carr + 3};   // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}}
-    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/ptr_ptr.pass.cpp b/libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp
deleted file mode 100644
--- a/libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-// -*- C++ -*-
-//===------------------------------ span ---------------------------------===//
-//
-// 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
-
-// <span>
-
-// constexpr span(pointer first, pointer last);
-// Requires: [first, last) shall be a valid range.
-//   If extent is not equal to dynamic_extent, then last - first shall be equal to extent.
-//
-
-#include <span>
-#include <cassert>
-#include <string>
-
-#include "test_macros.h"
-
-void checkCV()
-{
-                   int   arr[] = {1,2,3};
-    const          int  carr[] = {4,5,6};
-          volatile int  varr[] = {7,8,9};
-    const volatile int cvarr[] = {1,3,5};
-
-//  Types the same (dynamic sized)
-    {
-    std::span<               int> s1{  arr,   arr + 3}; // a span<               int> pointing at int.
-    std::span<const          int> s2{ carr,  carr + 3}; // a span<const          int> pointing at const int.
-    std::span<      volatile int> s3{ varr,  varr + 3}; // a span<      volatile int> pointing at volatile int.
-    std::span<const volatile int> s4{cvarr, cvarr + 3}; // a span<const volatile int> pointing at const volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
-    }
-
-//  Types the same (static sized)
-    {
-    std::span<               int,3> s1{  arr,   arr + 3};   // a span<               int> pointing at int.
-    std::span<const          int,3> s2{ carr,  carr + 3};   // a span<const          int> pointing at const int.
-    std::span<      volatile int,3> s3{ varr,  varr + 3};   // a span<      volatile int> pointing at volatile int.
-    std::span<const volatile int,3> s4{cvarr, cvarr + 3};   // a span<const volatile int> pointing at const volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() == 12);
-    }
-
-
-//  types different (dynamic sized)
-    {
-    std::span<const          int> s1{ arr,  arr + 3};       // a span<const          int> pointing at int.
-    std::span<      volatile int> s2{ arr,  arr + 3};       // a span<      volatile int> pointing at int.
-    std::span<      volatile int> s3{ arr,  arr + 3};       // a span<      volatile int> pointing at const int.
-    std::span<const volatile int> s4{ arr,  arr + 3};       // a span<const volatile int> pointing at int.
-    std::span<const volatile int> s5{carr, carr + 3};       // a span<const volatile int> pointing at const int.
-    std::span<const volatile int> s6{varr, varr + 3};       // a span<const volatile int> pointing at volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
-    }
-
-//  types different (static sized)
-    {
-    std::span<const          int,3> s1{ arr,  arr + 3}; // a span<const          int> pointing at int.
-    std::span<      volatile int,3> s2{ arr,  arr + 3}; // a span<      volatile int> pointing at int.
-    std::span<      volatile int,3> s3{ arr,  arr + 3}; // a span<      volatile int> pointing at const int.
-    std::span<const volatile int,3> s4{ arr,  arr + 3}; // a span<const volatile int> pointing at int.
-    std::span<const volatile int,3> s5{carr, carr + 3}; // a span<const volatile int> pointing at const int.
-    std::span<const volatile int,3> s6{varr, varr + 3}; // a span<const volatile int> pointing at volatile int.
-    assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18);
-    }
-}
-
-
-template <typename T>
-constexpr bool testConstexprSpan()
-{
-    constexpr T val[2] = {};
-    std::span<const T>   s1{val, val+2};
-    std::span<const T,2> s2{val, val+2};
-    return
-        s1.data() == &val[0] && s1.size() == 2
-    &&  s2.data() == &val[0] && s2.size() == 2;
-}
-
-
-template <typename T>
-void testRuntimeSpan()
-{
-    T val[2] = {};
-    std::span<T>   s1{val, val+2};
-    std::span<T,2> s2{val, val+2};
-    assert(s1.data() == &val[0] && s1.size() == 2);
-    assert(s2.data() == &val[0] && s2.size() == 2);
-}
-
-struct A{};
-
-int main(int, char**)
-{
-    static_assert(testConstexprSpan<int>(),    "");
-    static_assert(testConstexprSpan<long>(),   "");
-    static_assert(testConstexprSpan<double>(), "");
-    static_assert(testConstexprSpan<A>(),      "");
-
-    testRuntimeSpan<int>();
-    testRuntimeSpan<long>();
-    testRuntimeSpan<double>();
-    testRuntimeSpan<std::string>();
-    testRuntimeSpan<A>();
-
-    checkCV();
-
-  return 0;
-}
diff --git a/libcxx/test/std/containers/views/span.cons/range.fail.cpp b/libcxx/test/std/containers/views/span.cons/range.fail.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/range.fail.cpp
@@ -0,0 +1,119 @@
+//===------------------------------ span ---------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// <span>
+
+//  template<class R>
+//    constexpr explicit(extent != dynamic_extent) span(R&& r);
+//
+// Let U be remove_reference_t<ranges::range_reference_t<R>>.
+// Remarks: This constructor shall not participate in overload resolution unless:
+//   - R satisfies ranges::contiguous_range and ranges::sized_range,
+//   - Either R satisfies ranges::borrowed_range or is_const_v<element_type> is true,
+//   - remove_cvref_t<R> is not a specialization of span,
+//   - remove_cvref_t<R> is not a specialization of array,
+//   — is_array_v<remove_cvref_t<R>> is false,
+//   - is_convertible_v<U(*)[], element_type(*)[] is true
+//
+
+#include <span>
+#include <deque>
+#include <forward_list>
+#include <list>
+#include <ranges>
+#include <vector>
+
+#include "simple_range.h"
+#include "test_macros.h"
+
+template <typename T>
+struct IsARange {
+  T* begin();
+  T* end();
+};
+
+template <class T>
+struct DisabledBorrowedRange {
+  T* begin();
+  T* end();
+};
+
+template <class T>
+inline constexpr bool std::ranges::enable_borrowed_range<DisabledBorrowedRange<T>> = false;
+
+template<class T, std::size_t N>
+struct SpecializationOfArray : std::array<T, N> {};
+
+void check_type_wrong() {
+  SimpleRange<int, 1> r{};
+  std::span<float> s1{r.begin(), r.end()};   // expected-error {{no matching constructor for initialization of 'std::span<float>'}}
+  std::span<float, 1> s2{r, 1};   // expected-error {{no matching constructor for initialization of 'std::span<float, 1>'}}
+
+  std::span<const int> s3{std::deque<int>()};  // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+  std::span<const int> s4{std::list<int>()};  // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+  std::span<const int> s5{std::forward_list<int>()};  // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+}
+
+void check_cv_dynamic_extent() {
+  IsARange<const int> c;
+  IsARange<const volatile int> cv;
+  IsARange<volatile int> v;
+
+  std::span<int> s1{c};  // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+  std::span<int> s2{v};  // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+  std::span<int> s3{cv}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+  std::span<const int> s4{v}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+  std::span<const int> s5{cv}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
+  std::span<volatile int> s6{c}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+  std::span<volatile int> s7{cv}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}}
+}
+void check_invalid_range() {
+  std::span<int> s5{DisabledBorrowedRange<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+  std::span<int> s6{SpecializationOfArray<int, 1>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+}
+
+void check_cv_static_extent() {
+  SimpleRange<const int, 1> c{};
+  SimpleRange<const volatile int, 1> cv{};
+  SimpleRange<volatile int, 1> v{};
+  std::span<int, 1> s1{c};  // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}}
+  std::span<int, 1> s2{v};  // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}}
+  std::span<int, 1> s3{cv}; // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}}
+  std::span<const int, 1> s4{v}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 1>'}}
+  std::span<const int, 1> s5{cv}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 1>'}}
+  std::span<volatile int, 1> s6{c}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 1>'}}
+  std::span<volatile int, 1> s7{cv}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 1>'}}
+}
+
+template<class T, size_t extent, class Range>
+std::span<T, extent> createImplicitSpan(Range&& r) {
+  return {r}; // expected-error {{chosen constructor is explicit in copy-initialization}}
+}
+
+void check_explicit_constructor() {
+  SimpleRange<int, 1> r{};
+  createImplicitSpan<int, 1>(r);
+}
+
+int main(int, char**) {
+  //  Making non-const spans from const sources (a temporary binds to `const &`)
+  {
+    std::span<int> s1{IsARange<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+    std::span<int> s3{std::vector<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}}
+  }
+
+  check_type_wrong();
+  check_invalid_range();
+  check_cv_static_extent();
+  check_cv_dynamic_extent();
+  check_explicit_constructor();
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/span.cons/range.pass.cpp b/libcxx/test/std/containers/views/span.cons/range.pass.cpp
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/range.pass.cpp
@@ -0,0 +1,88 @@
+//===------------------------------ span ---------------------------------===//
+//
+// 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
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// <span>
+
+//  template<class R>
+//    constexpr explicit(extent != dynamic_extent) span(R&& r);
+//
+// Let U be remove_reference_t<ranges::range_reference_t<R>>.
+// Remarks: This constructor shall not participate in overload resolution unless:
+//   - R satisfies ranges::contiguous_range and ranges::sized_range,
+//   - Either R satisfies ranges::borrowed_range or is_const_v<element_type> is true,
+//   - remove_cvref_t<R> is not a specialization of span,
+//   - remove_cvref_t<R> is not a specialization of array,
+//   — is_array_v<remove_cvref_t<R>> is false,
+//   - is_convertible_v<rU(*)[], element_type(*)[] is true
+
+
+#include <span>
+#include <cassert>
+#include <vector>
+
+#include "simple_range.h"
+#include "test_macros.h"
+
+// TODO: convert to using std::is_constructible_v
+void check_cv()
+{
+    std::vector<int> v  = {1,2,3};
+
+//  types the same
+    {
+    std::span<int> s1{v};
+    std::span<int, 3> s2{v};
+    }
+
+//  types different
+    {
+    std::span<const int> s1{v};
+    std::span<const int, 3> s2{v};
+    std::span<volatile int> s3{v};
+    std::span<volatile int, 3> s4{v};
+    std::span<const volatile int> s5{v};
+    std::span<const volatile int, 3> s6{v};
+    }
+
+//  Constructing a const view from a temporary
+    {
+    std::span<const int> s1{std::vector<int>()};
+    std::span<const int, 1> s2{std::vector<int>()};
+    }
+}
+
+template <class T, size_t Extent>
+constexpr bool test_from_range() {
+  SimpleRange<T, 3> val{};
+  std::span<T, Extent> s{val};
+  assert(s.size() == val.size());
+  assert(s.data() == val.data());
+  return true;
+}
+
+struct A{};
+
+constexpr bool test() {
+  assert((test_from_range<int, std::dynamic_extent>()));
+  assert((test_from_range<int, 3>()));
+  assert((test_from_range<A, std::dynamic_extent>()));
+  assert((test_from_range<A, 3>()));
+  return true;
+}
+
+int main(int, char**)
+{
+    test();
+    static_assert(test());
+
+  check_cv();
+
+  return 0;
+}
diff --git a/libcxx/test/std/containers/views/span.cons/simple_range.h b/libcxx/test/std/containers/views/span.cons/simple_range.h
new file mode 100644
--- /dev/null
+++ b/libcxx/test/std/containers/views/span.cons/simple_range.h
@@ -0,0 +1,30 @@
+#pragma once
+
+template <class T, size_t Size>
+struct SimpleRange {
+    constexpr T *data() {
+      return elements;
+    }
+    constexpr const T *data() const {
+      return elements;
+    }
+    constexpr T *begin() {
+      return elements;
+    }
+    constexpr const T *begin() const {
+      return elements;
+    }
+    constexpr T *end() {
+      return elements + Size;
+    }
+    constexpr const T* end() const {
+      return elements + Size;
+    }
+    constexpr T const *getV() const {
+      return elements;
+    }
+    constexpr size_t size() const {
+      return Size;
+    }
+    T elements[Size]{};
+};