[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:
@@ -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"
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
86
libcxx/test/std/containers/views/span.cons/range.pass.cpp
Normal file
86
libcxx/test/std/containers/views/span.cons/range.pass.cpp
Normal 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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user