[libc++] Implement P1394r4 for span: range constructor

Implement https://wg21.link/p1394 which allows span to be constructible
from any contiguous forwarding-range that has a compatible element type.

Fixes https://bugs.llvm.org/show_bug.cgi?id=51443

Reviewed By: ldionne, Quuxplusone, #libc

Differential Revision: https://reviews.llvm.org/D110503
This commit is contained in:
Joe Loser
2021-10-08 16:57:44 -04:00
parent 57c56cf20c
commit 3a208c6894
36 changed files with 520 additions and 729 deletions

View File

@@ -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","|Complete|","14.0"
"`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"
1 Paper # Group Paper Name Meeting Status First released version
135
136 `P0883 <https://wg21.link/P0883>`__ LWG Fixing Atomic Initialization Belfast |Complete| [#note-P0883]_ 13.0
137 `P1391 <https://wg21.link/P1391>`__ LWG Range constructor for std::string_view Belfast |Complete| 14.0
138 `P1394 <https://wg21.link/P1394>`__ LWG Range constructor for std::span Belfast * * |Complete| 14.0
139 `P1456 <https://wg21.link/P1456>`__ LWG Move-only views Belfast * *
140 `P1622 <https://wg21.link/P1622>`__ LWG Mandating the Standard Library: Clause 32 - Thread support library Belfast * *
141 `P1645 <https://wg21.link/P1645>`__ LWG constexpr for numeric algorithms Belfast |Complete| 12.0

View File

@@ -56,18 +56,18 @@ public:
// [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 @@ private:
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>
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,9 +129,13 @@ template<class Container>
#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 <__ranges/size.h>
#include <array> // for array
#include <cstddef> // for byte
#include <iterator> // for iterators
@@ -155,46 +159,28 @@ template <typename _Tp, size_t _Extent = dynamic_extent> class span;
template <class _Tp>
struct __is_span_impl : public 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>
struct __is_std_array_impl : public false_type {};
struct __is_std_array : false_type {};
template <class _Tp, size_t _Sz>
struct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {};
struct __is_std_array<array<_Tp, _Sz>> : true_type {};
template <class _Tp>
struct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {};
struct __is_std_span : false_type {};
template <class _Tp, class _ElementType, class = void>
struct __is_span_compatible_container : public false_type {};
template <class _Tp, class _ElementType>
struct __is_span_compatible_container<_Tp, _ElementType,
void_t<
// is not a specialization of span
enable_if_t<!__is_span<_Tp>::value, nullptr_t>,
// is not a specialization of array
enable_if_t<!__is_std_array<_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
decltype(data(declval<_Tp>())),
decltype(size(declval<_Tp>())),
// remove_pointer_t<decltype(data(cont))>(*)[] is convertible to ElementType(*)[]
enable_if_t<
is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[],
_ElementType(*)[]>,
nullptr_t>
>>
: public true_type {};
template <class _Tp, size_t _Sz>
struct __is_std_span<span<_Tp, _Sz>> : true_type {};
#if !defined(_LIBCPP_HAS_NO_RANGES)
template <class _Range, class _ElementType>
concept __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 +210,31 @@ public:
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)"); }
#if !defined(_LIBCPP_HAS_NO_RANGES)
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((__last - __first >= 0), "invalid range in span's constructor (iterator, sentinel)");
_LIBCPP_ASSERT(__last - __first == _Extent,
"invalid range in span's constructor (iterator, sentinel): last - first != extent");
}
#endif
_LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {}
@@ -241,21 +248,13 @@ public:
_LIBCPP_INLINE_VISIBILITY
constexpr span(const array<_OtherElementType, _Extent>& __arr) noexcept : __data{__arr.data()} {}
template <class _Container>
#if !defined(_LIBCPP_HAS_NO_RANGES)
template <__span_compatible_range<element_type> _Range>
_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)");
}
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 +401,24 @@ 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}, __size{__count} {}
_LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{static_cast<size_t>(distance(__f, __l))} {}
#if !defined(_LIBCPP_HAS_NO_RANGES)
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(__last - __first) {}
#endif
template <size_t _Sz>
_LIBCPP_INLINE_VISIBILITY
@@ -419,18 +434,11 @@ public:
_LIBCPP_INLINE_VISIBILITY
constexpr span(const array<_OtherElementType, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {}
template <class _Container>
#if !defined(_LIBCPP_HAS_NO_RANGES)
template <__span_compatible_range<element_type> _Range>
_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)} {}
constexpr span(_Range&& __r) : __data(ranges::data(__r)), __size{ranges::size(__r)} {}
# endif
template <class _OtherElementType, size_t _OtherExtent>
_LIBCPP_INLINE_VISIBILITY
@@ -556,7 +564,12 @@ auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept
-> enable_if_t<!is_const_v<_Tp>, decltype(__s.__as_writable_bytes())>
{ return __s.__as_writable_bytes(); }
#if !defined(_LIBCPP_HAS_NO_RANGES)
// Deduction guides
template<contiguous_iterator _It, class _EndOrSize>
span(_It, _EndOrSize) -> span<remove_reference_t<iter_reference_t<_It>>>;
#endif
template<class _Tp, size_t _Sz>
span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>;
@@ -566,11 +579,10 @@ template<class _Tp, size_t _Sz>
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 !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

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -1,121 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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;
}

View File

@@ -1,145 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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;
}

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,9 +6,16 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <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>;
//
@@ -18,12 +25,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>
@@ -34,10 +37,25 @@
#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));
@@ -51,7 +69,9 @@ int main(int, char**)
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};
@@ -67,7 +87,9 @@ int main(int, char**)
assert(s.size() == arr.size());
assert(s.data() == arr.data());
}
}
void test_range_std_container() {
{
std::string str{"ABCDE"};
std::span s{str};
@@ -83,6 +105,14 @@ int main(int, char**)
assert(s.size() == str.size());
assert(s.data() == str.data());
}
}
int main(int, char**)
{
test_iterator_sentinel();
test_c_array();
test_std_array();
test_range_std_container();
return 0;
}

View File

@@ -0,0 +1,72 @@
//===---------------------------------------------------------------------===//
//
// 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
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <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 <iterator>
#include <type_traits>
template <size_t Extent>
constexpr void test_constructibility() {
struct Other {};
static_assert(std::is_constructible_v<std::span<int, Extent>, int*, size_t>);
static_assert(!std::is_constructible_v<std::span<int, Extent>, const int*, size_t>);
static_assert(std::is_constructible_v<std::span<const int, Extent>, int*, size_t>);
static_assert(std::is_constructible_v<std::span<const int, Extent>, const int*, size_t>);
static_assert(!std::is_constructible_v<std::span<int, Extent>, volatile int*, size_t>);
static_assert(!std::is_constructible_v<std::span<int, Extent>, const volatile int*, size_t>);
static_assert(!std::is_constructible_v<std::span<const int, Extent>, volatile int*, size_t>);
static_assert(!std::is_constructible_v<std::span<const int, Extent>, const volatile int*, size_t>);
static_assert(!std::is_constructible_v<std::span<volatile int, Extent>, const int*, size_t>);
static_assert(!std::is_constructible_v<std::span<volatile int, Extent>, const volatile int*, size_t>);
static_assert(
!std::is_constructible_v<std::span<int, Extent>, double*, size_t>); // iterator type differs from span type
static_assert(!std::is_constructible_v<std::span<int, Extent>, size_t, size_t>);
static_assert(!std::is_constructible_v<std::span<int, Extent>, Other*, size_t>); // unrelated iterator type
}
template <class T>
constexpr bool test_ctor() {
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;
}
constexpr bool test() {
test_constructibility<std::dynamic_extent>();
test_constructibility<3>();
struct A {};
test_ctor<int>();
test_ctor<A>();
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@@ -0,0 +1,37 @@
//===---------------------------------------------------------------------===//
//
// 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
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <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 <cstddef>
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**) {
// explicit constructor necessary
int arr[] = {1, 2, 3};
createImplicitSpan<int, 1>(arr, 3);
std::span<const int> sp = {0, 0}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}}
return 0;
}

View File

@@ -0,0 +1,67 @@
//===---------------------------------------------------------------------===//
//
// 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
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <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>
#include "test_iterators.h"
template <class T, class Sentinel>
constexpr bool test_ctor() {
T val[2] = {};
auto s1 = std::span<T>(std::begin(val), Sentinel(std::end(val)));
auto s2 = std::span<T, 2>(std::begin(val), Sentinel(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;
}
template <size_t Extent>
constexpr void test_constructibility() {
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*>);
static_assert(!std::is_constructible_v<std::span<int, Extent>, int*, float*>); // types wrong
}
constexpr bool test() {
test_constructibility<std::dynamic_extent>();
test_constructibility<3>();
struct A {};
assert((test_ctor<int, int*>()));
assert((test_ctor<int, sized_sentinel<int*>>()));
assert((test_ctor<A, A*>()));
assert((test_ctor<A, sized_sentinel<A*>>()));
return true;
}
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@@ -0,0 +1,37 @@
//===---------------------------------------------------------------------===//
//
// 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
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <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 <iterator>
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**) {
// explicit constructor necessary
int arr[] = {1, 2, 3};
createImplicitSpan<int, 1>(std::begin(arr), std::end(arr));
return 0;
}

View File

@@ -1,73 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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;
}

View File

@@ -1,113 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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;
}

View File

@@ -1,73 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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;
}

View File

@@ -1,113 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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;
}

View File

@@ -0,0 +1,86 @@
//===---------------------------------------------------------------------===//
//
// 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
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>
// template<class R>
// constexpr explicit(Extent != dynamic_extent) span(R&& r);
#include <span>
#include <cassert>
#include <ranges>
#include <string_view>
#include <type_traits>
#include <vector>
#include "test_iterators.h"
template <class T, size_t Extent>
constexpr void test_from_range() {
T val[3]{};
std::span<T, Extent> s{val};
assert(s.size() == std::size(val));
assert(s.data() == std::data(val));
}
struct A {};
constexpr bool test() {
test_from_range<int, std::dynamic_extent>();
test_from_range<int, 3>();
test_from_range<A, std::dynamic_extent>();
test_from_range<A, 3>();
return true;
}
static_assert(!std::is_constructible_v<std::span<int>, std::vector<float>&>); // wrong type
static_assert(!std::is_constructible_v<std::span<int, 3>, std::vector<float>&>); // wrong type
static_assert(std::is_constructible_v<std::span<int>, std::vector<int>&>); // non-borrowed lvalue
static_assert(std::is_constructible_v<std::span<int, 3>, std::vector<int>&>); // non-borrowed lvalue
static_assert(std::is_constructible_v<std::span<const int>, std::vector<int>&>); // non-borrowed lvalue
static_assert(std::is_constructible_v<std::span<const int, 3>, std::vector<int>&>); // non-borrowed lvalue
static_assert(!std::is_constructible_v<std::span<int>, const std::vector<int>&>); // non-borrowed const lvalue
static_assert(!std::is_constructible_v<std::span<int, 3>, const std::vector<int>&>); // non-borrowed const lvalue
static_assert(std::is_constructible_v<std::span<const int>, const std::vector<int>&>); // non-borrowed const lvalue
static_assert(std::is_constructible_v<std::span<const int, 3>, const std::vector<int>&>); // non-borrowed const lvalue
static_assert(std::is_constructible_v<std::span<const int>, std::vector<int>>); // non-borrowed rvalue
static_assert(std::is_constructible_v<std::span<const int, 3>, std::vector<int>>); // non-borrowed rvalue
static_assert(!std::is_constructible_v<std::span<int>, std::vector<int>&&>); // non-borrowed rvalue
static_assert(!std::is_constructible_v<std::span<int, 3>, std::vector<int>&&>); // non-borrowed rvalue
static_assert(std::is_constructible_v<std::span<int>, std::ranges::subrange<contiguous_iterator<int*>>>); // contiguous borrowed rvalue
static_assert(std::is_constructible_v<std::span<int, 3>, std::ranges::subrange<contiguous_iterator<int*>>>); // contiguous borrowed rvalue
static_assert(!std::is_constructible_v<std::span<int>, std::ranges::subrange<random_access_iterator<int*>>>); // non-contiguous borrowed rvalue
static_assert(!std::is_constructible_v<std::span<int, 3>, std::ranges::subrange<random_access_iterator<int*>>>); // non-contiguous borrowed rvalue
using BorrowedContiguousSizedRange = std::string_view;
static_assert(std::is_constructible_v<std::span<const char>, BorrowedContiguousSizedRange>);
static_assert(std::is_constructible_v<std::span<const char, 3>, BorrowedContiguousSizedRange>);
static_assert(!std::is_constructible_v<std::span<char>, BorrowedContiguousSizedRange>);
static_assert(!std::is_constructible_v<std::span<char, 3>, BorrowedContiguousSizedRange>);
static_assert(std::is_convertible_v<BorrowedContiguousSizedRange&, std::span<const char>>);
static_assert(!std::is_convertible_v<BorrowedContiguousSizedRange&, std::span<const char, 3>>);
static_assert(!std::is_convertible_v<BorrowedContiguousSizedRange&, std::span<char>>);
static_assert(!std::is_convertible_v<BorrowedContiguousSizedRange&, std::span<char, 3>>);
static_assert(std::is_convertible_v<const BorrowedContiguousSizedRange&, std::span<const char>>);
static_assert(!std::is_convertible_v<const BorrowedContiguousSizedRange&, std::span<const char, 3>>);
int main(int, char**) {
test();
static_assert(test());
return 0;
}

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>

View File

@@ -6,6 +6,10 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-has-no-incomplete-ranges
// AppleClang 12.0.0 doesn't fully support ranges/concepts
// XFAIL: apple-clang-12.0.0
// <span>