diff options
| author | Marshall Clow <mclow.lists@gmail.com> | 2018-07-24 03:01:02 +0000 |
|---|---|---|
| committer | Marshall Clow <mclow.lists@gmail.com> | 2018-07-24 03:01:02 +0000 |
| commit | 8a0794b722bd42d12c58295c69b659e79c73a903 (patch) | |
| tree | 7196b1ef2596473c513eea075695c45a27aece08 /libcxx | |
| parent | 0ed11a979298453c73a489441152b470a2cd742e (diff) | |
| download | bcm5719-llvm-8a0794b722bd42d12c58295c69b659e79c73a903.tar.gz bcm5719-llvm-8a0794b722bd42d12c58295c69b659e79c73a903.zip | |
Implement <span>. Reviewed as https://reviews.llvm.org/D49338
llvm-svn: 337804
Diffstat (limited to 'libcxx')
42 files changed, 5020 insertions, 0 deletions
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index e44ff3ef364..c60e61e6df8 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -128,6 +128,7 @@ set(files set setjmp.h shared_mutex + span sstream stack stdbool.h diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 70f82a775e3..e17c3a2f68a 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -559,6 +559,10 @@ module std [system] { header "experimental/set" export * } + module span { + header "span" + export * + } module string { header "experimental/string" export * diff --git a/libcxx/include/span b/libcxx/include/span new file mode 100644 index 00000000000..b1a13dd0244 --- /dev/null +++ b/libcxx/include/span @@ -0,0 +1,606 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP_SPAN +#define _LIBCPP_SPAN + +/* + span synopsis + +namespace std { + +// constants +inline constexpr ptrdiff_t dynamic_extent = -1; + +// [views.span], class template span +template <class ElementType, ptrdiff_t Extent = dynamic_extent> + class span; + +// [span.comparison], span comparison operators +template <class T, ptrdiff_t X, class U, ptrdiff_t Y> + constexpr bool operator==(span<T, X> l, span<U, Y> r); +template <class T, ptrdiff_t X, class U, ptrdiff_t Y> + constexpr bool operator!=(span<T, X> l, span<U, Y> r); +template <class T, ptrdiff_t X, class U, ptrdiff_t Y> + constexpr bool operator<(span<T, X> l, span<U, Y> r); +template <class T, ptrdiff_t X, class U, ptrdiff_t Y> + constexpr bool operator<=(span<T, X> l, span<U, Y> r); +template <class T, ptrdiff_t X, class U, ptrdiff_t Y> + constexpr bool operator>(span<T, X> l, span<U, Y> r); +template <class T, ptrdiff_t X, class U, ptrdiff_t Y> + constexpr bool operator>=(span<T, X> l, span<U, Y> r); + +// [span.objectrep], views of object representation +template <class ElementType, ptrdiff_t Extent> + span<const byte, ((Extent == dynamic_extent) ? dynamic_extent : + (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_bytes(span<ElementType, Extent> s) noexcept; + +template <class ElementType, ptrdiff_t Extent> + span< byte, ((Extent == dynamic_extent) ? dynamic_extent : + (static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept; + + +namespace std { +template <class ElementType, ptrdiff_t Extent = dynamic_extent> +class span { +public: + // constants and types + using element_type = ElementType; + using value_type = remove_cv_t<ElementType>; + using index_type = ptrdiff_t; + using difference_type = ptrdiff_t; + using pointer = element_type*; + using reference = element_type&; + using iterator = implementation-defined; + using const_iterator = implementation-defined; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + static constexpr index_type extent = Extent; + + // [span.cons], span constructors, copy, assignment, and destructor + constexpr span() noexcept; + constexpr span(pointer ptr, index_type count); + constexpr span(pointer firstElem, pointer lastElem); + 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 span(Container& cont); + template <class Container> + constexpr span(const Container& cont); + constexpr span(const span& other) noexcept = default; + template <class OtherElementType, ptrdiff_t OtherExtent> + constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept; + ~span() noexcept = default; + constexpr span& operator=(const span& other) noexcept = default; + + // [span.sub], span subviews + template <ptrdiff_t Count> + constexpr span<element_type, Count> first() const; + template <ptrdiff_t Count> + constexpr span<element_type, Count> last() const; + template <ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent> + constexpr span<element_type, see below> subspan() const; + + constexpr span<element_type, dynamic_extent> first(index_type count) const; + constexpr span<element_type, dynamic_extent> last(index_type count) const; + constexpr span<element_type, dynamic_extent> subspan(index_type offset, index_type count = dynamic_extent) const; + + // [span.obs], span observers + constexpr index_type size() const noexcept; + constexpr index_type size_bytes() const noexcept; + constexpr bool empty() const noexcept; + + // [span.elem], span element access + constexpr reference operator[](index_type idx) const; + constexpr reference operator()(index_type idx) const; + constexpr pointer data() const noexcept; + + // [span.iterators], span iterator support + constexpr iterator begin() const noexcept; + constexpr iterator end() const noexcept; + constexpr const_iterator cbegin() const noexcept; + constexpr const_iterator cend() const noexcept; + constexpr reverse_iterator rbegin() const noexcept; + constexpr reverse_iterator rend() const noexcept; + constexpr const_reverse_iterator crbegin() const noexcept; + constexpr const_reverse_iterator crend() const noexcept; + +private: + pointer data_; // exposition only + index_type size_; // exposition only +}; + +template<class T, size_t N> + span(T (&)[N]) -> span<T, N>; + +template<class T, size_t N> + span(array<T, N>&) -> span<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>; + +} // namespace std + +*/ + +#include <cstddef> // for ptrdiff_t +#include <iterator> // for iterators +#include <array> // for array +#include <type_traits> // for remove_cv, etc +#include <cstddef> // for byte + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +inline constexpr ptrdiff_t dynamic_extent = -1; +template <typename _Tp, ptrdiff_t _Extent = dynamic_extent> class span; + + +template <class _Tp> +struct __is_span_impl : public false_type {}; + +template <class _Tp, ptrdiff_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 {}; + +template <class _Tp, size_t _Sz> +struct __is_std_array_impl<array<_Tp, _Sz>> : public true_type {}; + +template <class _Tp> +struct __is_std_array : public __is_std_array_impl<remove_cv_t<_Tp>> {}; + +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 + typename enable_if<!__is_span<_Tp>::value, nullptr_t>::type, + // is not a specialization of array + typename enable_if<!__is_std_array<_Tp>::value, nullptr_t>::type, + // is_array_v<Container> is false, + typename enable_if<!is_array_v<_Tp>, nullptr_t>::type, + // 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(*)[] + typename enable_if< + is_convertible_v<remove_pointer_t<decltype(data(declval<_Tp &>()))>(*)[], + _ElementType(*)[]>, + nullptr_t>::type + >> + : public true_type {}; + + +template <typename _Tp, ptrdiff_t _Extent> +class _LIBCPP_TEMPLATE_VIS span { +public: +// constants and types + using element_type = _Tp; + using value_type = remove_cv_t<_Tp>; + using index_type = ptrdiff_t; + using difference_type = ptrdiff_t; + using pointer = _Tp *; + using const_pointer = const _Tp *; // not in standard + using reference = _Tp &; + using const_reference = const _Tp &; // not in standard + using iterator = __wrap_iter<pointer>; + using const_iterator = __wrap_iter<const_pointer>; + using reverse_iterator = _VSTD::reverse_iterator<iterator>; + using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>; + + static constexpr index_type extent = _Extent; + static_assert (_Extent >= 0, "Can't have a span with an extent < 0"); + +// [span.cons], span constructors, copy, assignment, and destructor + _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr} + { static_assert(_Extent == 0, "Can't default construct a statically sized span with size > 0"); } + + constexpr span (const span&) noexcept = default; + constexpr span& operator=(const span&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr} + { (void)__count; _LIBCPP_ASSERT(_Extent == __count, "size mismatch in span's constructor (ptr, len)"); } + _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f} + { (void)__l; _LIBCPP_ASSERT(_Extent == distance(__f, __l), "size mismatch in span's constructor (ptr, ptr)"); } + + _LIBCPP_INLINE_VISIBILITY constexpr span(element_type (&__arr)[_Extent]) noexcept : __data{__arr} {} + _LIBCPP_INLINE_VISIBILITY constexpr span( array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {} + _LIBCPP_INLINE_VISIBILITY constexpr span(const array<value_type, _Extent>& __arr) noexcept : __data{__arr.data()} {} + + template <class _Container> + inline _LIBCPP_INLINE_VISIBILITY + constexpr 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 (container))"); } + + template <class _Container> + inline _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)} + { _LIBCPP_ASSERT(_Extent == _VSTD::size(__c), "size mismatch in span's constructor (const container)"); } + + template <class _OtherElementType> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const span<_OtherElementType, _Extent>& __other, + enable_if_t< + is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, + nullptr_t> = nullptr) + : __data{__other.data()} {} + + template <class _OtherElementType> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const span<_OtherElementType, dynamic_extent>& __other, + enable_if_t< + is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, + nullptr_t> = nullptr) noexcept + : __data{__other.data()} { _LIBCPP_ASSERT(_Extent == __other.size(), "size mismatch in span's constructor (other span)"); } + + +// ~span() noexcept = default; + + template <ptrdiff_t _Count> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span<element_type, _Count> first() const noexcept + { + static_assert(_Count >= 0, "Count must be >= 0 in span::first()"); + static_assert(_Count <= _Extent, "Count out of range in span::first()"); + return {data(), _Count}; + } + + template <ptrdiff_t _Count> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span<element_type, _Count> last() const noexcept + { + static_assert(_Count >= 0, "Count must be >= 0 in span::last()"); + static_assert(_Count <= _Extent, "Count out of range in span::last()"); + return {data() + size() - _Count, _Count}; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept + { + _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)"); + return {data(), __count}; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr span<element_type, dynamic_extent> last(index_type __count) const noexcept + { + _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)"); + return {data() + size() - __count, __count}; + } + + template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent> + inline _LIBCPP_INLINE_VISIBILITY + constexpr auto subspan() const noexcept + -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> + { + _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()"); + return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; + } + + + inline _LIBCPP_INLINE_VISIBILITY + constexpr span<element_type, dynamic_extent> + subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept + { + _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)"); + _LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "Count out of range in span::subspan(offset, count)"); + if (__count == dynamic_extent) + return {data() + __offset, size() - __offset}; + _LIBCPP_ASSERT(__offset + __count <= size(), "count + offset out of range in span::subspan(offset, count)"); + return {data() + __offset, __count}; + } + + _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return _Extent; } + _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return _Extent * sizeof(element_type); } + _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return _Extent == 0; } + + _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept + { + _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>[] index out of bounds"); + return __data[__idx]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept + { + _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T,N>() index out of bounds"); + return __data[__idx]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } + +// [span.iter], span iterator support + _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } + _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } + _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } + _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } + + _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept + { + pointer __p = __data; + __data = __other.__data; + __other.__data = __p; + } + + _LIBCPP_INLINE_VISIBILITY span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept + { return {reinterpret_cast<const byte *>(data()), size_bytes()}; } + + _LIBCPP_INLINE_VISIBILITY span<byte, _Extent * sizeof(element_type)> __as_writeable_bytes() const noexcept + { return {reinterpret_cast<byte *>(data()), size_bytes()}; } + +private: + pointer __data; + +}; + + +template <typename _Tp> +class _LIBCPP_TEMPLATE_VIS span<_Tp, dynamic_extent> { +private: + +public: +// constants and types + using element_type = _Tp; + using value_type = remove_cv_t<_Tp>; + using index_type = ptrdiff_t; + using difference_type = ptrdiff_t; + using pointer = _Tp *; + using const_pointer = const _Tp *; // not in standard + using reference = _Tp &; + using const_reference = const _Tp &; // not in standard + using iterator = __wrap_iter<pointer>; + using const_iterator = __wrap_iter<const_pointer>; + using reverse_iterator = _VSTD::reverse_iterator<iterator>; + using const_reverse_iterator = _VSTD::reverse_iterator<const_iterator>; + + static constexpr index_type extent = dynamic_extent; + +// [span.cons], span constructors, copy, assignment, and destructor + _LIBCPP_INLINE_VISIBILITY constexpr span() noexcept : __data{nullptr}, __size{0} {} + + constexpr span (const span&) noexcept = default; + constexpr span& operator=(const span&) noexcept = default; + + _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __ptr, index_type __count) : __data{__ptr}, __size{__count} {} + _LIBCPP_INLINE_VISIBILITY constexpr span(pointer __f, pointer __l) : __data{__f}, __size{distance(__f, __l)} {} + + template <size_t _Sz> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(element_type (&__arr)[_Sz]) noexcept : __data{__arr}, __size{_Sz} {} + + template <size_t _Sz> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} + + template <size_t _Sz> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const array<value_type, _Sz>& __arr) noexcept : __data{__arr.data()}, __size{_Sz} {} + + template <class _Container> + inline _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{(index_type) _VSTD::size(__c)} {} + + template <class _Container> + inline _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{(index_type) _VSTD::size(__c)} {} + + + template <class _OtherElementType, ptrdiff_t _OtherExtent> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span(const span<_OtherElementType, _OtherExtent>& __other, + enable_if_t< + is_convertible_v<_OtherElementType(*)[], element_type (*)[]>, + nullptr_t> = nullptr) noexcept + : __data{__other.data()}, __size{__other.size()} {} + +// ~span() noexcept = default; + + template <ptrdiff_t _Count> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span<element_type, _Count> first() const noexcept + { + static_assert(_Count >= 0); + _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::first()"); + return {data(), _Count}; + } + + template <ptrdiff_t _Count> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span<element_type, _Count> last() const noexcept + { + static_assert(_Count >= 0); + _LIBCPP_ASSERT(_Count <= size(), "Count out of range in span::last()"); + return {data() + size() - _Count, _Count}; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr span<element_type, dynamic_extent> first(index_type __count) const noexcept + { + _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::first(count)"); + return {data(), __count}; + } + + _LIBCPP_INLINE_VISIBILITY + constexpr span<element_type, dynamic_extent> last (index_type __count) const noexcept + { + _LIBCPP_ASSERT(__count >= 0 && __count <= size(), "Count out of range in span::last(count)"); + return {data() + size() - __count, __count}; + } + + template <ptrdiff_t _Offset, ptrdiff_t _Count = dynamic_extent> + inline _LIBCPP_INLINE_VISIBILITY + constexpr span<_Tp, dynamic_extent> subspan() const noexcept + { + _LIBCPP_ASSERT(_Offset >= 0 && _Offset <= size(), "Offset out of range in span::subspan()"); + _LIBCPP_ASSERT(_Count == dynamic_extent || _Offset + _Count <= size(), "Count out of range in span::subspan()"); + return {data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count}; + } + + constexpr span<element_type, dynamic_extent> + inline _LIBCPP_INLINE_VISIBILITY + subspan(index_type __offset, index_type __count = dynamic_extent) const noexcept + { + _LIBCPP_ASSERT( __offset >= 0 && __offset <= size(), "Offset out of range in span::subspan(offset, count)"); + _LIBCPP_ASSERT((__count >= 0 && __count <= size()) || __count == dynamic_extent, "count out of range in span::subspan(offset, count)"); + if (__count == dynamic_extent) + return {data() + __offset, size() - __offset}; + _LIBCPP_ASSERT(__offset + __count <= size(), "Offset + count out of range in span::subspan(offset, count)"); + return {data() + __offset, __count}; + } + + _LIBCPP_INLINE_VISIBILITY constexpr index_type size() const noexcept { return __size; } + _LIBCPP_INLINE_VISIBILITY constexpr index_type size_bytes() const noexcept { return __size * sizeof(element_type); } + _LIBCPP_INLINE_VISIBILITY constexpr bool empty() const noexcept { return __size == 0; } + + _LIBCPP_INLINE_VISIBILITY constexpr reference operator[](index_type __idx) const noexcept + { + _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>[] index out of bounds"); + return __data[__idx]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept + { + _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span<T>() index out of bounds"); + return __data[__idx]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } + +// [span.iter], span iterator support + _LIBCPP_INLINE_VISIBILITY constexpr iterator begin() const noexcept { return iterator(data()); } + _LIBCPP_INLINE_VISIBILITY constexpr iterator end() const noexcept { return iterator(data() + size()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cbegin() const noexcept { return const_iterator(data()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_iterator cend() const noexcept { return const_iterator(data() + size()); } + _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); } + _LIBCPP_INLINE_VISIBILITY constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); } + _LIBCPP_INLINE_VISIBILITY constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); } + + _LIBCPP_INLINE_VISIBILITY constexpr void swap(span &__other) noexcept + { + pointer __p = __data; + __data = __other.__data; + __other.__data = __p; + + index_type __sz = __size; + __size = __other.__size; + __other.__size = __sz; + } + + _LIBCPP_INLINE_VISIBILITY span<const byte, dynamic_extent> __as_bytes() const noexcept + { return {reinterpret_cast<const byte *>(data()), size_bytes()}; } + + _LIBCPP_INLINE_VISIBILITY span<byte, dynamic_extent> __as_writeable_bytes() const noexcept + { return {reinterpret_cast<byte *>(data()), size_bytes()}; } + +private: + pointer __data; + index_type __size; +}; + +template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> + constexpr bool + operator==(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return equal(__lhs.begin(), __lhs.end(), __rhs.begin(), __rhs.end()); } + +template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> + constexpr bool + operator!=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return !(__rhs == __lhs); } + +template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> + constexpr bool + operator< (const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return lexicographical_compare (__lhs.begin(), __lhs.end(), __rhs.begin(), __rhs.end()); } + +template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> + constexpr bool + operator<=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return !(__rhs < __lhs); } + +template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> + constexpr bool + operator> (const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return __rhs < __lhs; } + +template <class _Tp1, ptrdiff_t _Extent1, class _Tp2, ptrdiff_t _Extent2> + constexpr bool + operator>=(const span<_Tp1, _Extent1>& __lhs, const span<_Tp2, _Extent2>& __rhs) + { return !(__lhs < __rhs); } + +// as_bytes & as_writeable_bytes +template <class _Tp, ptrdiff_t _Extent> + auto as_bytes(span<_Tp, _Extent> __s) noexcept + -> decltype(__s.__as_bytes()) + { return __s.__as_bytes(); } + +template <class _Tp, ptrdiff_t _Extent> + auto as_writeable_bytes(span<_Tp, _Extent> __s) noexcept + -> typename enable_if<!is_const_v<_Tp>, decltype(__s.__as_writeable_bytes())>::type + { return __s.__as_writeable_bytes(); } + +template <class _Tp, ptrdiff_t _Extent> + constexpr void swap(span<_Tp, _Extent> &__lhs, span<_Tp, _Extent> &__rhs) noexcept + { __lhs.swap(__rhs); } + + +// Deduction guides +template<class _Tp, size_t _Sz> + span(_Tp (&)[_Sz]) -> span<_Tp, _Sz>; + +template<class _Tp, size_t _Sz> + span(array<_Tp, _Sz>&) -> span<_Tp, _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>; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER > 17 +#endif // _LIBCPP_SPAN diff --git a/libcxx/test/libcxx/double_include.sh.cpp b/libcxx/test/libcxx/double_include.sh.cpp index 0f2d1e08905..dfc3d011668 100644 --- a/libcxx/test/libcxx/double_include.sh.cpp +++ b/libcxx/test/libcxx/double_include.sh.cpp @@ -102,6 +102,7 @@ #ifndef _LIBCPP_HAS_NO_THREADS #include <shared_mutex> #endif +#include <span> #include <sstream> #include <stack> #include <stdbool.h> diff --git a/libcxx/test/std/containers/views/span.comparison/op.eq.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.eq.pass.cpp new file mode 100644 index 00000000000..96305458046 --- /dev/null +++ b/libcxx/test/std/containers/views/span.comparison/op.eq.pass.cpp @@ -0,0 +1,168 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class T, ptrdiff_t X, class U, ptrdiff_t Y> +// constexpr bool operator==(span<T, X> l, span<U, Y> r); +// +// +// Effects: Equivalent to: return equal(l.begin(), l.end(), r.begin(), r.end()); +// + +#include <span> +#include <cassert> + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span<const int> csp0d{}; + constexpr std::span<const int> csp1d{iArr1, 10}; + constexpr std::span<const int> csp2d{iArr1 + 3, 2}; + constexpr std::span<const int> csp3d{iArr1 + 1, 2}; + constexpr std::span<const int> csp4d{iArr1 + 6, 2}; + + constexpr std::span<const int, 0> csp0s{}; + constexpr std::span<const int, 10> csp1s{iArr1, 10}; + constexpr std::span<const int, 2> csp2s{iArr1 + 3, 2}; + constexpr std::span<const int, 2> csp3s{iArr1 + 1, 2}; + constexpr std::span<const int, 2> csp4s{iArr1 + 6, 2}; + + static_assert( (csp0d == csp0d), ""); + static_assert( (csp0s == csp0s), ""); + static_assert( (csp0s == csp0d), ""); + static_assert( (csp0d == csp0s), ""); + + static_assert(!(csp0d == csp1d), ""); + static_assert(!(csp0s == csp1s), ""); + static_assert(!(csp0s == csp1d), ""); + static_assert(!(csp0d == csp1s), ""); + + static_assert( (csp1d == csp1s), ""); + static_assert( (csp1s == csp1d), ""); + + static_assert( (csp2d == csp3d), ""); + static_assert( (csp2s == csp3s), ""); + static_assert( (csp2d == csp3s), ""); + static_assert( (csp2s == csp3d), ""); + + static_assert( (csp2d == csp3d), ""); + static_assert( (csp2s == csp3s), ""); + static_assert( (csp2d == csp3s), ""); + static_assert( (csp2s == csp3d), ""); + + static_assert(!(csp2d == csp4d), ""); + static_assert(!(csp2s == csp4s), ""); + static_assert(!(csp2d == csp4s), ""); + static_assert(!(csp2s == csp4d), ""); + + static_assert(!(csp4d == csp2d), ""); + static_assert(!(csp4s == csp2s), ""); + static_assert(!(csp4d == csp2s), ""); + static_assert(!(csp4s == csp2d), ""); + + std::span<int> sp0d{}; + std::span<int> sp1d{iArr2, 10}; + std::span<int> sp2d{iArr2 + 3, 2}; + std::span<int> sp3d{iArr2 + 1, 2}; + std::span<int> sp4d{iArr2 + 6, 2}; + + std::span<int, 0> sp0s{}; + std::span<int, 10> sp1s{iArr2, 10}; + std::span<int, 2> sp2s{iArr2 + 3, 2}; + std::span<int, 2> sp3s{iArr2 + 1, 2}; + std::span<int, 2> sp4s{iArr2 + 6, 2}; + + assert( (sp0d == sp0d)); + assert( (sp0s == sp0s)); + assert( (sp0s == sp0d)); + assert( (sp0d == sp0s)); + + assert(!(sp0d == sp1d)); + assert(!(sp0s == sp1s)); + assert(!(sp0s == sp1d)); + assert(!(sp0d == sp1s)); + + assert( (sp1d == sp1s)); + assert( (sp1s == sp1d)); + + assert( (sp2d == sp3d)); + assert( (sp2s == sp3s)); + assert( (sp2d == sp3s)); + assert( (sp2s == sp3d)); + + assert( (sp2d == sp3d)); + assert( (sp2s == sp3s)); + assert( (sp2d == sp3s)); + assert( (sp2s == sp3d)); + + assert(!(sp2d == sp4d)); + assert(!(sp2s == sp4s)); + assert(!(sp2d == sp4s)); + assert(!(sp2s == sp4d)); + + assert(!(sp4d == sp2d)); + assert(!(sp4s == sp2s)); + assert(!(sp4d == sp2s)); + assert(!(sp4s == sp2d)); + +// cross type comparisons + assert( (csp0d == sp0d)); + assert( (csp0s == sp0s)); + assert( (csp0s == sp0d)); + assert( (csp0d == sp0s)); + + assert(!(csp0d == sp1d)); + assert(!(csp0s == sp1s)); + assert(!(csp0s == sp1d)); + assert(!(csp0d == sp1s)); + + assert( (csp1d == sp1s)); + assert( (csp1s == sp1d)); + + assert( (csp2d == sp3d)); + assert( (csp2s == sp3s)); + assert( (csp2d == sp3s)); + assert( (csp2s == sp3d)); + + assert( (csp2d == sp3d)); + assert( (csp2s == sp3s)); + assert( (csp2d == sp3s)); + assert( (csp2s == sp3d)); + + assert(!(csp2d == sp4d)); + assert(!(csp2s == sp4s)); + assert(!(csp2d == sp4s)); + assert(!(csp2s == sp4d)); + + assert(!(csp4d == sp2d)); + assert(!(csp4s == sp2s)); + assert(!(csp4d == sp2s)); + assert(!(csp4s == sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(std::span<const float>{fArr1} == std::span<const int>{iArr1}, ""); + static_assert(std::span<const int>{iArr1} == std::span<const float>{fArr1}, ""); + assert(std::span<float>{fArr2} == std::span<int>{iArr2}); + assert(std::span<int>{iArr2} == std::span<float>{fArr2}); + + static_assert(!(std::span<const int>{iArr1, 9} == std::span<const float>{fArr1, 8}), ""); +}
\ No newline at end of file diff --git a/libcxx/test/std/containers/views/span.comparison/op.ge.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.ge.pass.cpp new file mode 100644 index 00000000000..8ec1b9a590e --- /dev/null +++ b/libcxx/test/std/containers/views/span.comparison/op.ge.pass.cpp @@ -0,0 +1,153 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class T, ptrdiff_t X, class U, ptrdiff_t Y> +// constexpr bool operator>=(span<T, X> l, span<U, Y> r); +// +// +// Effects: Equivalent to: return !(l < r); +// + +#include <span> +#include <cassert> + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span<const int> csp0d{}; + constexpr std::span<const int> csp1d{iArr1, 10}; + constexpr std::span<const int> csp2d{iArr1 + 3, 2}; + constexpr std::span<const int> csp3d{iArr1 + 1, 2}; + constexpr std::span<const int> csp4d{iArr1 + 6, 2}; + + constexpr std::span<const int, 0> csp0s{}; + constexpr std::span<const int, 10> csp1s{iArr1, 10}; + constexpr std::span<const int, 2> csp2s{iArr1 + 3, 2}; + constexpr std::span<const int, 2> csp3s{iArr1 + 1, 2}; + constexpr std::span<const int, 2> csp4s{iArr1 + 6, 2}; + + static_assert( (csp0d >= csp0d), ""); + static_assert( (csp0s >= csp0s), ""); + static_assert( (csp0s >= csp0d), ""); + static_assert( (csp0d >= csp0s), ""); + + static_assert(!(csp0d >= csp1d), ""); + static_assert(!(csp0s >= csp1s), ""); + static_assert(!(csp0s >= csp1d), ""); + static_assert(!(csp0d >= csp1s), ""); + + static_assert( (csp1d >= csp1s), ""); + static_assert( (csp1s >= csp1d), ""); + + static_assert( (csp2d >= csp3d), ""); + static_assert( (csp2s >= csp3s), ""); + static_assert( (csp2d >= csp3s), ""); + static_assert( (csp2s >= csp3d), ""); + + static_assert(!(csp2d >= csp4d), ""); + static_assert(!(csp2s >= csp4s), ""); + static_assert(!(csp2d >= csp4s), ""); + static_assert(!(csp2s >= csp4d), ""); + + static_assert( (csp4d >= csp2d), ""); + static_assert( (csp4s >= csp2s), ""); + static_assert( (csp4d >= csp2s), ""); + static_assert( (csp4s >= csp2d), ""); + + std::span<int> sp0d{}; + std::span<int> sp1d{iArr2, 10}; + std::span<int> sp2d{iArr2 + 3, 2}; + std::span<int> sp3d{iArr2 + 1, 2}; + std::span<int> sp4d{iArr2 + 6, 2}; + + std::span<int, 0> sp0s{}; + std::span<int, 10> sp1s{iArr2, 10}; + std::span<int, 2> sp2s{iArr2 + 3, 2}; + std::span<int, 2> sp3s{iArr2 + 1, 2}; + std::span<int, 2> sp4s{iArr2 + 6, 2}; + + assert( (sp0d >= sp0d)); + assert( (sp0s >= sp0s)); + assert( (sp0s >= sp0d)); + assert( (sp0d >= sp0s)); + + assert(!(sp0d >= sp1d)); + assert(!(sp0s >= sp1s)); + assert(!(sp0s >= sp1d)); + assert(!(sp0d >= sp1s)); + + assert( (sp1d >= sp1s)); + assert( (sp1s >= sp1d)); + + assert( (sp2d >= sp3d)); + assert( (sp2s >= sp3s)); + assert( (sp2d >= sp3s)); + assert( (sp2s >= sp3d)); + + assert(!(sp2d >= sp4d)); + assert(!(sp2s >= sp4s)); + assert(!(sp2d >= sp4s)); + assert(!(sp2s >= sp4d)); + + assert( (sp4d > sp2d)); + assert( (sp4s > sp2s)); + assert( (sp4d > sp2s)); + assert( (sp4s > sp2d)); + +// cross type comparisons + assert( (csp0d >= sp0d)); + assert( (csp0s >= sp0s)); + assert( (csp0s >= sp0d)); + assert( (csp0d >= sp0s)); + + assert(!(csp0d >= sp1d)); + assert(!(csp0s >= sp1s)); + assert(!(csp0s >= sp1d)); + assert(!(csp0d >= sp1s)); + + assert( (csp1d >= sp1s)); + assert( (csp1s >= sp1d)); + + assert( (csp2d >= sp3d)); + assert( (csp2s >= sp3s)); + assert( (csp2d >= sp3s)); + assert( (csp2s >= sp3d)); + + assert(!(csp2d >= sp4d)); + assert(!(csp2s >= sp4s)); + assert(!(csp2d >= sp4s)); + assert(!(csp2s >= sp4d)); + + assert( (csp4d > sp2d)); + assert( (csp4s > sp2s)); + assert( (csp4d > sp2s)); + assert( (csp4s > sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(!(std::span<const float>{fArr1, 8} >= std::span<const int>{iArr1, 9}), ""); + static_assert(!(std::span<const int>{iArr1, 8} >= std::span<const float>{fArr1, 9}), ""); + assert( (std::span<float>{fArr2} >= std::span<int>{iArr2})); + assert( (std::span<int>{iArr2} >= std::span<float>{fArr2})); + + static_assert( (std::span<const int>{iArr1, 9} >= std::span<const float>{fArr1, 8}), ""); +} diff --git a/libcxx/test/std/containers/views/span.comparison/op.gt.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.gt.pass.cpp new file mode 100644 index 00000000000..345a291a62b --- /dev/null +++ b/libcxx/test/std/containers/views/span.comparison/op.gt.pass.cpp @@ -0,0 +1,154 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class T, ptrdiff_t X, class U, ptrdiff_t Y> +// constexpr bool operator>(span<T, X> l, span<U, Y> r); +// +// +// Effects: Equivalent to: return (r < l); +// + +#include <span> +#include <cassert> + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span<const int> csp0d{}; + constexpr std::span<const int> csp1d{iArr1, 10}; + constexpr std::span<const int> csp2d{iArr1 + 3, 2}; + constexpr std::span<const int> csp3d{iArr1 + 1, 2}; + constexpr std::span<const int> csp4d{iArr1 + 6, 2}; + + constexpr std::span<const int, 0> csp0s{}; + constexpr std::span<const int, 10> csp1s{iArr1, 10}; + constexpr std::span<const int, 2> csp2s{iArr1 + 3, 2}; + constexpr std::span<const int, 2> csp3s{iArr1 + 1, 2}; + constexpr std::span<const int, 2> csp4s{iArr1 + 6, 2}; + + static_assert(!(csp0d > csp0d), ""); + static_assert(!(csp0s > csp0s), ""); + static_assert(!(csp0s > csp0d), ""); + static_assert(!(csp0d > csp0s), ""); + + static_assert(!(csp0d > csp1d), ""); + static_assert(!(csp0s > csp1s), ""); + static_assert(!(csp0s > csp1d), ""); + static_assert(!(csp0d > csp1s), ""); + + static_assert(!(csp1d > csp1s), ""); + static_assert(!(csp1s > csp1d), ""); + + static_assert(!(csp2d > csp3d), ""); + static_assert(!(csp2s > csp3s), ""); + static_assert(!(csp2d > csp3s), ""); + static_assert(!(csp2s > csp3d), ""); + + static_assert(!(csp2d > csp4d), ""); + static_assert(!(csp2s > csp4s), ""); + static_assert(!(csp2d > csp4s), ""); + static_assert(!(csp2s > csp4d), ""); + + static_assert( (csp4d > csp2d), ""); + static_assert( (csp4s > csp2s), ""); + static_assert( (csp4d > csp2s), ""); + static_assert( (csp4s > csp2d), ""); + + std::span<int> sp0d{}; + std::span<int> sp1d{iArr2, 10}; + std::span<int> sp2d{iArr2 + 3, 2}; + std::span<int> sp3d{iArr2 + 1, 2}; + std::span<int> sp4d{iArr2 + 6, 2}; + + std::span<int, 0> sp0s{}; + std::span<int, 10> sp1s{iArr2, 10}; + std::span<int, 2> sp2s{iArr2 + 3, 2}; + std::span<int, 2> sp3s{iArr2 + 1, 2}; + std::span<int, 2> sp4s{iArr2 + 6, 2}; + + assert(!(sp0d > sp0d)); + assert(!(sp0s > sp0s)); + assert(!(sp0s > sp0d)); + assert(!(sp0d > sp0s)); + + assert(!(sp0d > sp1d)); + assert(!(sp0s > sp1s)); + assert(!(sp0s > sp1d)); + assert(!(sp0d > sp1s)); + + assert(!(sp1d > sp1s)); + assert(!(sp1s > sp1d)); + + assert(!(sp2d > sp3d)); + assert(!(sp2s > sp3s)); + assert(!(sp2d > sp3s)); + assert(!(sp2s > sp3d)); + + assert(!(sp2d > sp4d)); + assert(!(sp2s > sp4s)); + assert(!(sp2d > sp4s)); + assert(!(sp2s > sp4d)); + + assert( (sp4d > sp2d)); + assert( (sp4s > sp2s)); + assert( (sp4d > sp2s)); + assert( (sp4s > sp2d)); + +// cross type comparisons + assert(!(csp0d > sp0d)); + assert(!(csp0s > sp0s)); + assert(!(csp0s > sp0d)); + assert(!(csp0d > sp0s)); + + assert(!(csp0d > sp1d)); + assert(!(csp0s > sp1s)); + assert(!(csp0s > sp1d)); + assert(!(csp0d > sp1s)); + + assert(!(csp1d > sp1s)); + assert(!(csp1s > sp1d)); + + assert(!(csp2d > sp3d)); + assert(!(csp2s > sp3s)); + assert(!(csp2d > sp3s)); + assert(!(csp2s > sp3d)); + + assert(!(csp2d > sp4d)); + assert(!(csp2s > sp4s)); + assert(!(csp2d > sp4s)); + assert(!(csp2s > sp4d)); + + assert( (csp4d > sp2d)); + assert( (csp4s > sp2s)); + assert( (csp4d > sp2s)); + assert( (csp4s > sp2d)); + + +// More cross-type comparisons (int vs float) + static_assert(!(std::span<const float>{fArr1, 8} > std::span<const int>{iArr1, 9}), ""); + static_assert(!(std::span<const int>{iArr1, 8} > std::span<const float>{fArr1, 9}), ""); + assert(!(std::span<float>{fArr2} > std::span<int>{iArr2})); + assert(!(std::span<int>{iArr2} > std::span<float>{fArr2})); + + static_assert( (std::span<const int>{iArr1, 9} > std::span<const float>{fArr1, 8}), ""); +}
\ No newline at end of file diff --git a/libcxx/test/std/containers/views/span.comparison/op.le.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.le.pass.cpp new file mode 100644 index 00000000000..f2fbc860908 --- /dev/null +++ b/libcxx/test/std/containers/views/span.comparison/op.le.pass.cpp @@ -0,0 +1,153 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class T, ptrdiff_t X, class U, ptrdiff_t Y> +// constexpr bool operator<=(span<T, X> l, span<U, Y> r); +// +// +// Effects: Equivalent to: return !(r < l); +// + +#include <span> +#include <cassert> + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span<const int> csp0d{}; + constexpr std::span<const int> csp1d{iArr1, 10}; + constexpr std::span<const int> csp2d{iArr1 + 3, 2}; + constexpr std::span<const int> csp3d{iArr1 + 1, 2}; + constexpr std::span<const int> csp4d{iArr1 + 6, 2}; + + constexpr std::span<const int, 0> csp0s{}; + constexpr std::span<const int, 10> csp1s{iArr1, 10}; + constexpr std::span<const int, 2> csp2s{iArr1 + 3, 2}; + constexpr std::span<const int, 2> csp3s{iArr1 + 1, 2}; + constexpr std::span<const int, 2> csp4s{iArr1 + 6, 2}; + + static_assert( (csp0d <= csp0d), ""); + static_assert( (csp0s <= csp0s), ""); + static_assert( (csp0s <= csp0d), ""); + static_assert( (csp0d <= csp0s), ""); + + static_assert( (csp0d <= csp1d), ""); + static_assert( (csp0s <= csp1s), ""); + static_assert( (csp0s <= csp1d), ""); + static_assert( (csp0d <= csp1s), ""); + + static_assert( (csp1d <= csp1s), ""); + static_assert( (csp1s <= csp1d), ""); + + static_assert( (csp2d <= csp3d), ""); + static_assert( (csp2s <= csp3s), ""); + static_assert( (csp2d <= csp3s), ""); + static_assert( (csp2s <= csp3d), ""); + + static_assert( (csp2d <= csp4d), ""); + static_assert( (csp2s <= csp4s), ""); + static_assert( (csp2d <= csp4s), ""); + static_assert( (csp2s <= csp4d), ""); + + static_assert(!(csp4d <= csp2d), ""); + static_assert(!(csp4s <= csp2s), ""); + static_assert(!(csp4d <= csp2s), ""); + static_assert(!(csp4s <= csp2d), ""); + + std::span<int> sp0d{}; + std::span<int> sp1d{iArr2, 10}; + std::span<int> sp2d{iArr2 + 3, 2}; + std::span<int> sp3d{iArr2 + 1, 2}; + std::span<int> sp4d{iArr2 + 6, 2}; + + std::span<int, 0> sp0s{}; + std::span<int, 10> sp1s{iArr2, 10}; + std::span<int, 2> sp2s{iArr2 + 3, 2}; + std::span<int, 2> sp3s{iArr2 + 1, 2}; + std::span<int, 2> sp4s{iArr2 + 6, 2}; + + assert( (sp0d <= sp0d)); + assert( (sp0s <= sp0s)); + assert( (sp0s <= sp0d)); + assert( (sp0d <= sp0s)); + + assert( (sp0d <= sp1d)); + assert( (sp0s <= sp1s)); + assert( (sp0s <= sp1d)); + assert( (sp0d <= sp1s)); + + assert( (sp1d <= sp1s)); + assert( (sp1s <= sp1d)); + + assert( (sp2d <= sp3d)); + assert( (sp2s <= sp3s)); + assert( (sp2d <= sp3s)); + assert( (sp2s <= sp3d)); + + assert( (sp2d <= sp4d)); + assert( (sp2s <= sp4s)); + assert( (sp2d <= sp4s)); + assert( (sp2s <= sp4d)); + + assert(!(sp4d <= sp2d)); + assert(!(sp4s <= sp2s)); + assert(!(sp4d <= sp2s)); + assert(!(sp4s <= sp2d)); + +// cross type comparisons + assert( (csp0d <= sp0d)); + assert( (csp0s <= sp0s)); + assert( (csp0s <= sp0d)); + assert( (csp0d <= sp0s)); + + assert( (csp0d <= sp1d)); + assert( (csp0s <= sp1s)); + assert( (csp0s <= sp1d)); + assert( (csp0d <= sp1s)); + + assert( (csp1d <= sp1s)); + assert( (csp1s <= sp1d)); + + assert( (csp2d <= sp3d)); + assert( (csp2s <= sp3s)); + assert( (csp2d <= sp3s)); + assert( (csp2s <= sp3d)); + + assert( (csp2d <= sp4d)); + assert( (csp2s <= sp4s)); + assert( (csp2d <= sp4s)); + assert( (csp2s <= sp4d)); + + assert(!(csp4d <= sp2d)); + assert(!(csp4s <= sp2s)); + assert(!(csp4d <= sp2s)); + assert(!(csp4s <= sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(std::span<const float>{fArr1, 8} <= std::span<const int>{iArr1, 9}, ""); + static_assert(std::span<const int>{iArr1, 8} <= std::span<const float>{fArr1, 9}, ""); + assert( (std::span<float>{fArr2} <= std::span<int>{iArr2})); + assert( (std::span<int>{iArr2} <= std::span<float>{fArr2})); + + static_assert(!(std::span<const int>{iArr1, 9} <= std::span<const float>{fArr1, 8}), ""); +}
\ No newline at end of file diff --git a/libcxx/test/std/containers/views/span.comparison/op.lt.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.lt.pass.cpp new file mode 100644 index 00000000000..1a7de292e90 --- /dev/null +++ b/libcxx/test/std/containers/views/span.comparison/op.lt.pass.cpp @@ -0,0 +1,154 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class T, ptrdiff_t X, class U, ptrdiff_t Y> +// constexpr bool operator<(span<T, X> l, span<U, Y> r); +// +// +// Effects: Equivalent to: +// return lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); +// + +#include <span> +#include <cassert> + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span<const int> csp0d{}; + constexpr std::span<const int> csp1d{iArr1, 10}; + constexpr std::span<const int> csp2d{iArr1 + 3, 2}; + constexpr std::span<const int> csp3d{iArr1 + 1, 2}; + constexpr std::span<const int> csp4d{iArr1 + 6, 2}; + + constexpr std::span<const int, 0> csp0s{}; + constexpr std::span<const int, 10> csp1s{iArr1, 10}; + constexpr std::span<const int, 2> csp2s{iArr1 + 3, 2}; + constexpr std::span<const int, 2> csp3s{iArr1 + 1, 2}; + constexpr std::span<const int, 2> csp4s{iArr1 + 6, 2}; + + static_assert(!(csp0d < csp0d), ""); + static_assert(!(csp0s < csp0s), ""); + static_assert(!(csp0s < csp0d), ""); + static_assert(!(csp0d < csp0s), ""); + + static_assert( (csp0d < csp1d), ""); + static_assert( (csp0s < csp1s), ""); + static_assert( (csp0s < csp1d), ""); + static_assert( (csp0d < csp1s), ""); + + static_assert(!(csp1d < csp1s), ""); + static_assert(!(csp1s < csp1d), ""); + + static_assert(!(csp2d < csp3d), ""); + static_assert(!(csp2s < csp3s), ""); + static_assert(!(csp2d < csp3s), ""); + static_assert(!(csp2s < csp3d), ""); + + static_assert( (csp2d < csp4d), ""); + static_assert( (csp2s < csp4s), ""); + static_assert( (csp2d < csp4s), ""); + static_assert( (csp2s < csp4d), ""); + + static_assert(!(csp4d < csp2d), ""); + static_assert(!(csp4s < csp2s), ""); + static_assert(!(csp4d < csp2s), ""); + static_assert(!(csp4s < csp2d), ""); + + std::span<int> sp0d{}; + std::span<int> sp1d{iArr2, 10}; + std::span<int> sp2d{iArr2 + 3, 2}; + std::span<int> sp3d{iArr2 + 1, 2}; + std::span<int> sp4d{iArr2 + 6, 2}; + + std::span<int, 0> sp0s{}; + std::span<int, 10> sp1s{iArr2, 10}; + std::span<int, 2> sp2s{iArr2 + 3, 2}; + std::span<int, 2> sp3s{iArr2 + 1, 2}; + std::span<int, 2> sp4s{iArr2 + 6, 2}; + + assert(!(sp0d < sp0d)); + assert(!(sp0s < sp0s)); + assert(!(sp0s < sp0d)); + assert(!(sp0d < sp0s)); + + assert( (sp0d < sp1d)); + assert( (sp0s < sp1s)); + assert( (sp0s < sp1d)); + assert( (sp0d < sp1s)); + + assert(!(sp1d < sp1s)); + assert(!(sp1s < sp1d)); + + assert(!(sp2d < sp3d)); + assert(!(sp2s < sp3s)); + assert(!(sp2d < sp3s)); + assert(!(sp2s < sp3d)); + + assert( (sp2d < sp4d)); + assert( (sp2s < sp4s)); + assert( (sp2d < sp4s)); + assert( (sp2s < sp4d)); + + assert(!(sp4d < sp2d)); + assert(!(sp4s < sp2s)); + assert(!(sp4d < sp2s)); + assert(!(sp4s < sp2d)); + +// cross type comparisons + assert(!(csp0d < sp0d)); + assert(!(csp0s < sp0s)); + assert(!(csp0s < sp0d)); + assert(!(csp0d < sp0s)); + + assert( (csp0d < sp1d)); + assert( (csp0s < sp1s)); + assert( (csp0s < sp1d)); + assert( (csp0d < sp1s)); + + assert(!(csp1d < sp1s)); + assert(!(csp1s < sp1d)); + + assert(!(csp2d < sp3d)); + assert(!(csp2s < sp3s)); + assert(!(csp2d < sp3s)); + assert(!(csp2s < sp3d)); + + assert( (csp2d < sp4d)); + assert( (csp2s < sp4s)); + assert( (csp2d < sp4s)); + assert( (csp2s < sp4d)); + + assert(!(csp4d < sp2d)); + assert(!(csp4s < sp2s)); + assert(!(csp4d < sp2s)); + assert(!(csp4s < sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(std::span<const float>{fArr1, 8} < std::span<const int>{iArr1, 9}, ""); + static_assert(std::span<const int>{iArr1, 8} < std::span<const float>{fArr1, 9}, ""); + assert(!(std::span<float>{fArr2} < std::span<int>{iArr2})); + assert(!(std::span<int>{iArr2} < std::span<float>{fArr2})); + + static_assert(!(std::span<const int>{iArr1, 9} < std::span<const float>{fArr1, 8}), ""); +}
\ No newline at end of file diff --git a/libcxx/test/std/containers/views/span.comparison/op.ne.pass.cpp b/libcxx/test/std/containers/views/span.comparison/op.ne.pass.cpp new file mode 100644 index 00000000000..ecf05b31749 --- /dev/null +++ b/libcxx/test/std/containers/views/span.comparison/op.ne.pass.cpp @@ -0,0 +1,168 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class T, ptrdiff_t X, class U, ptrdiff_t Y> +// constexpr bool operator!=(span<T, X> l, span<U, Y> r); +// +// +// Effects: Equivalent to: return !(l == r); +// + +#include <span> +#include <cassert> + +#include "test_macros.h" + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; + int iArr2[] = { 0, 1, 2, 1, 2, 5, 6, 7, 8, 9}; +constexpr float fArr1[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + float fArr2[] = {0., 1., 2., 1., 2., 5., 6., 7., 8., 9.}; + + +int main () { + + constexpr std::span<const int> csp0d{}; + constexpr std::span<const int> csp1d{iArr1, 10}; + constexpr std::span<const int> csp2d{iArr1 + 3, 2}; + constexpr std::span<const int> csp3d{iArr1 + 1, 2}; + constexpr std::span<const int> csp4d{iArr1 + 6, 2}; + + constexpr std::span<const int, 0> csp0s{}; + constexpr std::span<const int, 10> csp1s{iArr1, 10}; + constexpr std::span<const int, 2> csp2s{iArr1 + 3, 2}; + constexpr std::span<const int, 2> csp3s{iArr1 + 1, 2}; + constexpr std::span<const int, 2> csp4s{iArr1 + 6, 2}; + + static_assert(!(csp0d != csp0d), ""); + static_assert(!(csp0s != csp0s), ""); + static_assert(!(csp0s != csp0d), ""); + static_assert(!(csp0d != csp0s), ""); + + static_assert( (csp0d != csp1d), ""); + static_assert( (csp0s != csp1s), ""); + static_assert( (csp0s != csp1d), ""); + static_assert( (csp0d != csp1s), ""); + + static_assert(!(csp1d != csp1s), ""); + static_assert(!(csp1s != csp1d), ""); + + static_assert(!(csp2d != csp3d), ""); + static_assert(!(csp2s != csp3s), ""); + static_assert(!(csp2d != csp3s), ""); + static_assert(!(csp2s != csp3d), ""); + + static_assert(!(csp2d != csp3d), ""); + static_assert(!(csp2s != csp3s), ""); + static_assert(!(csp2d != csp3s), ""); + static_assert(!(csp2s != csp3d), ""); + + static_assert( (csp2d != csp4d), ""); + static_assert( (csp2s != csp4s), ""); + static_assert( (csp2d != csp4s), ""); + static_assert( (csp2s != csp4d), ""); + + static_assert( (csp4d != csp2d), ""); + static_assert( (csp4s != csp2s), ""); + static_assert( (csp4d != csp2s), ""); + static_assert( (csp4s != csp2d), ""); + + std::span<int> sp0d{}; + std::span<int> sp1d{iArr2, 10}; + std::span<int> sp2d{iArr2 + 3, 2}; + std::span<int> sp3d{iArr2 + 1, 2}; + std::span<int> sp4d{iArr2 + 6, 2}; + + std::span<int, 0> sp0s{}; + std::span<int, 10> sp1s{iArr2, 10}; + std::span<int, 2> sp2s{iArr2 + 3, 2}; + std::span<int, 2> sp3s{iArr2 + 1, 2}; + std::span<int, 2> sp4s{iArr2 + 6, 2}; + + assert(!(sp0d != sp0d)); + assert(!(sp0s != sp0s)); + assert(!(sp0s != sp0d)); + assert(!(sp0d != sp0s)); + + assert( (sp0d != sp1d)); + assert( (sp0s != sp1s)); + assert( (sp0s != sp1d)); + assert( (sp0d != sp1s)); + + assert(!(sp1d != sp1s)); + assert(!(sp1s != sp1d)); + + assert(!(sp2d != sp3d)); + assert(!(sp2s != sp3s)); + assert(!(sp2d != sp3s)); + assert(!(sp2s != sp3d)); + + assert(!(sp2d != sp3d)); + assert(!(sp2s != sp3s)); + assert(!(sp2d != sp3s)); + assert(!(sp2s != sp3d)); + + assert( (sp2d != sp4d)); + assert( (sp2s != sp4s)); + assert( (sp2d != sp4s)); + assert( (sp2s != sp4d)); + + assert( (sp4d != sp2d)); + assert( (sp4s != sp2s)); + assert( (sp4d != sp2s)); + assert( (sp4s != sp2d)); + +// cross type comparisons + assert(!(csp0d != sp0d)); + assert(!(csp0s != sp0s)); + assert(!(csp0s != sp0d)); + assert(!(csp0d != sp0s)); + + assert( (csp0d != sp1d)); + assert( (csp0s != sp1s)); + assert( (csp0s != sp1d)); + assert( (csp0d != sp1s)); + + assert(!(csp1d != sp1s)); + assert(!(csp1s != sp1d)); + + assert(!(csp2d != sp3d)); + assert(!(csp2s != sp3s)); + assert(!(csp2d != sp3s)); + assert(!(csp2s != sp3d)); + + assert(!(csp2d != sp3d)); + assert(!(csp2s != sp3s)); + assert(!(csp2d != sp3s)); + assert(!(csp2s != sp3d)); + + assert( (csp2d != sp4d)); + assert( (csp2s != sp4s)); + assert( (csp2d != sp4s)); + assert( (csp2s != sp4d)); + + assert( (csp4d != sp2d)); + assert( (csp4s != sp2s)); + assert( (csp4d != sp2s)); + assert( (csp4s != sp2d)); + +// More cross-type comparisons (int vs float) + static_assert(!(std::span<const float>{fArr1} != std::span<const int>{iArr1}), ""); + static_assert(!(std::span<const int>{iArr1} != std::span<const float>{fArr1}), ""); + assert(!(std::span<float>{fArr2} != std::span<int>{iArr2})); + assert(!(std::span<int>{iArr2} != std::span<float>{fArr2})); + + static_assert( (std::span<const int>{iArr1, 9} != std::span<const float>{fArr1, 8}), ""); +}
\ No newline at end of file diff --git a/libcxx/test/std/containers/views/span.cons/array.fail.cpp b/libcxx/test/std/containers/views/span.cons/array.fail.cpp new file mode 100644 index 00000000000..7ef49fc4708 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/array.fail.cpp @@ -0,0 +1,72 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// 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; +// +// Remarks: These constructors shall not participate in overload resolution unless: +// — extent == dynamic_extent || N == extent is true, and +// — remove_pointer_t<decltype(data(arr))>(*)[] is convertible to ElementType(*)[]. +// + + +#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}; + +int main () +{ +// Size wrong + { + std::span<int, 2> s1(arr); // expected-error {{no matching constructor for initialization of 'std::span<int, 2>'}} + } + +// Type wrong + { + std::span<float> s1(arr); // expected-error {{no matching constructor for initialization of 'std::span<float>'}} + std::span<float, 3> s2(arr); // expected-error {{no matching constructor for initialization of 'std::span<float, 3>'}} + } + +// CV wrong (dynamically sized) + { + std::span< int> s1{ carr}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span< int> s2{ varr}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span< int> s3{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span<const int> s4{ varr}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}} + std::span<const int> s5{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}} + std::span< volatile int> s6{ carr}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}} + std::span< volatile int> s7{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}} + } + +// CV wrong (statically sized) + { + std::span< int,3> s1{ carr}; // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}} + std::span< int,3> s2{ varr}; // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}} + std::span< int,3> s3{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span<int, 3>'}} + std::span<const int,3> s4{ varr}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}} + std::span<const int,3> s5{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 3>'}} + std::span< volatile int,3> s6{ carr}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}} + std::span< volatile int,3> s7{cvarr}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 3>'}} + } +} diff --git a/libcxx/test/std/containers/views/span.cons/array.pass.cpp b/libcxx/test/std/containers/views/span.cons/array.pass.cpp new file mode 100644 index 00000000000..80a0f07f625 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/array.pass.cpp @@ -0,0 +1,123 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<size_t N> +// constexpr span(element_type (&arr)[N]) noexcept; +// +// Remarks: These constructors shall not participate in overload resolution unless: +// — extent == dynamic_extent || N == extent is true, and +// — remove_pointer_t<decltype(data(arr))>(*)[] is convertible to ElementType(*)[]. +// + + +#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}; // a span< int> pointing at int. + std::span<const int> s2{ carr}; // a span<const int> pointing at const int. + std::span< volatile int> s3{ varr}; // a span< volatile int> pointing at volatile int. + std::span<const volatile int> s4{cvarr}; // a span<const volatile int> pointing at const volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); + } + +// Types the same (static sized) + { + std::span< int,3> s1{ arr}; // a span< int> pointing at int. + std::span<const int,3> s2{ carr}; // a span<const int> pointing at const int. + std::span< volatile int,3> s3{ varr}; // a span< volatile int> pointing at volatile int. + std::span<const volatile int,3> s4{cvarr}; // a span<const volatile int> pointing at const volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 12); + } + + +// types different (dynamic sized) + { + std::span<const int> s1{ arr}; // a span<const int> pointing at int. + std::span< volatile int> s2{ arr}; // a span< volatile int> pointing at int. + std::span< volatile int> s3{ arr}; // a span< volatile int> pointing at const int. + std::span<const volatile int> s4{ arr}; // a span<const volatile int> pointing at int. + std::span<const volatile int> s5{carr}; // a span<const volatile int> pointing at const int. + std::span<const volatile int> s6{varr}; // a span<const volatile int> pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); + } + +// types different (static sized) + { + std::span<const int,3> s1{ arr}; // a span<const int> pointing at int. + std::span< volatile int,3> s2{ arr}; // a span< volatile int> pointing at int. + std::span< volatile int,3> s3{ arr}; // a span< volatile int> pointing at const int. + std::span<const volatile int,3> s4{ arr}; // a span<const volatile int> pointing at int. + std::span<const volatile int,3> s5{carr}; // a span<const volatile int> pointing at const int. + std::span<const volatile int,3> s6{varr}; // a span<const volatile int> pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() + s5.size() + s6.size() == 18); + } +} + + +template <typename T> +constexpr bool testConstexprSpan() +{ + constexpr T val[2] = {}; + + ASSERT_NOEXCEPT(std::span<const T> {val}); + ASSERT_NOEXCEPT(std::span<const T, 2>{val}); + std::span<const T> s1{val}; + std::span<const T, 2> s2{val}; + return + s1.data() == &val[0] && s1.size() == 2 + && s2.data() == &val[0] && s2.size() == 2; +} + + +template <typename T> +void testRuntimeSpan() +{ + T val[2] = {}; + ASSERT_NOEXCEPT(std::span<T> {val}); + ASSERT_NOEXCEPT(std::span<T, 2>{val}); + std::span<T> s1{val}; + std::span<T, 2> s2{val}; + assert(s1.data() == &val[0] && s1.size() == 2); + assert(s2.data() == &val[0] && s2.size() == 2); +} + +struct A{}; + +int main () +{ + 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(); +} diff --git a/libcxx/test/std/containers/views/span.cons/assign.pass.cpp b/libcxx/test/std/containers/views/span.cons/assign.pass.cpp new file mode 100644 index 00000000000..b5bd7ae00df --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/assign.pass.cpp @@ -0,0 +1,293 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr span& operator=(const span& other) noexcept = default; + +#include <span> +#include <cassert> +#include <string> +#include <utility> + +#include "test_macros.h" + +template <typename T> +constexpr bool doAssign(T lhs, T rhs) +{ + ASSERT_NOEXCEPT(std::declval<T&>() = rhs); + lhs = rhs; + return lhs.data() == rhs.data() + && lhs.size() == rhs.size(); +} + +struct A{}; + +constexpr int carr1[] = {1,2,3,4}; +constexpr int carr2[] = {3,4,5}; +constexpr int carr3[] = {7,8}; + int arr[] = {5,6,7,9}; +std::string strs[] = {"ABC", "DEF", "GHI"}; + + +int main () +{ + +// constexpr dynamically sized assignment + { +// On systems where 'ptrdiff_t' is a synonym for 'int', +// the call span(ptr, 0) selects the (pointer, index_type) constructor. +// On systems where 'ptrdiff_t' is NOT a synonym for 'int', +// it is ambiguous, because of 0 also being convertible to a null pointer +// and so the compiler can't choose between: +// span(pointer, index_type) +// and span(pointer, pointer) +// We cast zero to std::ptrdiff_t to remove that ambiguity. +// Example: +// On darwin x86_64, ptrdiff_t is the same as long int. +// On darwin i386, ptrdiff_t is the same as int. + constexpr std::span<const int> spans[] = { + {}, + {carr1, static_cast<std::ptrdiff_t>(0)}, + {carr1, 1}, + {carr1, 2}, + {carr1, 3}, + {carr1, 4}, + {carr2, static_cast<std::ptrdiff_t>(0)}, + {carr2, 1}, + {carr2, 2}, + {carr2, 3}, + {carr3, static_cast<std::ptrdiff_t>(0)}, + {carr3, 1}, + {carr3, 2} + }; + + static_assert(std::size(spans) == 13, "" ); + +// No for loops in constexpr land :-( + static_assert(doAssign(spans[0], spans[0]), ""); + static_assert(doAssign(spans[0], spans[1]), ""); + static_assert(doAssign(spans[0], spans[2]), ""); + static_assert(doAssign(spans[0], spans[3]), ""); + static_assert(doAssign(spans[0], spans[4]), ""); + static_assert(doAssign(spans[0], spans[5]), ""); + static_assert(doAssign(spans[0], spans[6]), ""); + static_assert(doAssign(spans[0], spans[7]), ""); + static_assert(doAssign(spans[0], spans[8]), ""); + static_assert(doAssign(spans[0], spans[9]), ""); + static_assert(doAssign(spans[0], spans[10]), ""); + static_assert(doAssign(spans[0], spans[11]), ""); + static_assert(doAssign(spans[0], spans[12]), ""); + + static_assert(doAssign(spans[1], spans[1]), ""); + static_assert(doAssign(spans[1], spans[2]), ""); + static_assert(doAssign(spans[1], spans[3]), ""); + static_assert(doAssign(spans[1], spans[4]), ""); + static_assert(doAssign(spans[1], spans[5]), ""); + static_assert(doAssign(spans[1], spans[6]), ""); + static_assert(doAssign(spans[1], spans[7]), ""); + static_assert(doAssign(spans[1], spans[8]), ""); + static_assert(doAssign(spans[1], spans[9]), ""); + static_assert(doAssign(spans[1], spans[10]), ""); + static_assert(doAssign(spans[1], spans[11]), ""); + static_assert(doAssign(spans[1], spans[12]), ""); + + static_assert(doAssign(spans[2], spans[2]), ""); + static_assert(doAssign(spans[2], spans[3]), ""); + static_assert(doAssign(spans[2], spans[4]), ""); + static_assert(doAssign(spans[2], spans[5]), ""); + static_assert(doAssign(spans[2], spans[6]), ""); + static_assert(doAssign(spans[2], spans[7]), ""); + static_assert(doAssign(spans[2], spans[8]), ""); + static_assert(doAssign(spans[2], spans[9]), ""); + static_assert(doAssign(spans[2], spans[10]), ""); + static_assert(doAssign(spans[2], spans[11]), ""); + static_assert(doAssign(spans[2], spans[12]), ""); + + static_assert(doAssign(spans[3], spans[3]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[10]), ""); + static_assert(doAssign(spans[3], spans[11]), ""); + static_assert(doAssign(spans[3], spans[12]), ""); + + static_assert(doAssign(spans[4], spans[4]), ""); + static_assert(doAssign(spans[4], spans[5]), ""); + static_assert(doAssign(spans[4], spans[6]), ""); + static_assert(doAssign(spans[4], spans[7]), ""); + static_assert(doAssign(spans[4], spans[8]), ""); + static_assert(doAssign(spans[4], spans[9]), ""); + static_assert(doAssign(spans[4], spans[10]), ""); + static_assert(doAssign(spans[4], spans[11]), ""); + static_assert(doAssign(spans[4], spans[12]), ""); + + static_assert(doAssign(spans[5], spans[5]), ""); + static_assert(doAssign(spans[5], spans[6]), ""); + static_assert(doAssign(spans[5], spans[7]), ""); + static_assert(doAssign(spans[5], spans[8]), ""); + static_assert(doAssign(spans[5], spans[9]), ""); + static_assert(doAssign(spans[5], spans[10]), ""); + static_assert(doAssign(spans[5], spans[11]), ""); + static_assert(doAssign(spans[5], spans[12]), ""); + + static_assert(doAssign(spans[6], spans[6]), ""); + static_assert(doAssign(spans[6], spans[7]), ""); + static_assert(doAssign(spans[6], spans[8]), ""); + static_assert(doAssign(spans[6], spans[9]), ""); + static_assert(doAssign(spans[6], spans[10]), ""); + static_assert(doAssign(spans[6], spans[11]), ""); + static_assert(doAssign(spans[6], spans[12]), ""); + + static_assert(doAssign(spans[7], spans[7]), ""); + static_assert(doAssign(spans[7], spans[8]), ""); + static_assert(doAssign(spans[7], spans[9]), ""); + static_assert(doAssign(spans[7], spans[10]), ""); + static_assert(doAssign(spans[7], spans[11]), ""); + static_assert(doAssign(spans[7], spans[12]), ""); + + static_assert(doAssign(spans[8], spans[8]), ""); + static_assert(doAssign(spans[8], spans[9]), ""); + static_assert(doAssign(spans[8], spans[10]), ""); + static_assert(doAssign(spans[8], spans[11]), ""); + static_assert(doAssign(spans[8], spans[12]), ""); + + static_assert(doAssign(spans[9], spans[9]), ""); + static_assert(doAssign(spans[9], spans[10]), ""); + static_assert(doAssign(spans[9], spans[11]), ""); + static_assert(doAssign(spans[9], spans[12]), ""); + + static_assert(doAssign(spans[10], spans[10]), ""); + static_assert(doAssign(spans[10], spans[11]), ""); + static_assert(doAssign(spans[10], spans[12]), ""); + + static_assert(doAssign(spans[11], spans[11]), ""); + static_assert(doAssign(spans[11], spans[12]), ""); + + static_assert(doAssign(spans[12], spans[12]), ""); + +// for (size_t i = 0; i < std::size(spans); ++i) +// for (size_t j = i; j < std::size(spans); ++j) +// static_assert(doAssign(spans[i], spans[j]), ""); + } + +// constexpr statically sized assignment + { + constexpr std::span<const int,2> spans[] = { + {carr1, 2}, + {carr1 + 1, 2}, + {carr1 + 2, 2}, + {carr2, 2}, + {carr2 + 1, 2}, + {carr3, 2} + }; + + static_assert(std::size(spans) == 6, "" ); + +// No for loops in constexpr land :-( + static_assert(doAssign(spans[0], spans[0]), ""); + static_assert(doAssign(spans[0], spans[1]), ""); + static_assert(doAssign(spans[0], spans[2]), ""); + static_assert(doAssign(spans[0], spans[3]), ""); + static_assert(doAssign(spans[0], spans[4]), ""); + static_assert(doAssign(spans[0], spans[5]), ""); + + static_assert(doAssign(spans[1], spans[1]), ""); + static_assert(doAssign(spans[1], spans[2]), ""); + static_assert(doAssign(spans[1], spans[3]), ""); + static_assert(doAssign(spans[1], spans[4]), ""); + static_assert(doAssign(spans[1], spans[5]), ""); + + static_assert(doAssign(spans[2], spans[2]), ""); + static_assert(doAssign(spans[2], spans[3]), ""); + static_assert(doAssign(spans[2], spans[4]), ""); + static_assert(doAssign(spans[2], spans[5]), ""); + + static_assert(doAssign(spans[3], spans[3]), ""); + static_assert(doAssign(spans[3], spans[4]), ""); + static_assert(doAssign(spans[3], spans[5]), ""); + + static_assert(doAssign(spans[4], spans[4]), ""); + static_assert(doAssign(spans[4], spans[5]), ""); + + static_assert(doAssign(spans[5], spans[5]), ""); + +// for (size_t i = 0; i < std::size(spans); ++i) +// for (size_t j = i; j < std::size(spans); ++j) +// static_assert(doAssign(spans[i], spans[j]), ""); + } + + +// dynamically sized assignment + { + std::span<int> spans[] = { + {}, + {arr, arr + 1}, + {arr, arr + 2}, + {arr, arr + 3}, + {arr + 1, arr + 3} // same size as s2 + }; + + for (size_t i = 0; i < std::size(spans); ++i) + for (size_t j = i; j < std::size(spans); ++j) + assert((doAssign(spans[i], spans[j]))); + } + +// statically sized assignment + { + std::span<int,2> spans[] = { + {arr, arr + 2}, + {arr + 1, arr + 3}, + {arr + 2, arr + 4} + }; + + for (size_t i = 0; i < std::size(spans); ++i) + for (size_t j = i; j < std::size(spans); ++j) + assert((doAssign(spans[i], spans[j]))); + } + +// dynamically sized assignment + { + std::span<std::string> spans[] = { + {strs, strs}, + {strs, strs + 1}, + {strs, strs + 2}, + {strs, strs + 3}, + {strs + 1, strs + 1}, + {strs + 1, strs + 2}, + {strs + 1, strs + 3}, + {strs + 2, strs + 2}, + {strs + 2, strs + 3}, + {strs + 3, strs + 3} + }; + + for (size_t i = 0; i < std::size(spans); ++i) + for (size_t j = i; j < std::size(spans); ++j) + assert((doAssign(spans[i], spans[j]))); + } + + { + std::span<std::string, 1> spans[] = { + {strs, strs + 1}, + {strs + 1, strs + 2}, + {strs + 2, strs + 3} + }; + + for (size_t i = 0; i < std::size(spans); ++i) + for (size_t j = i; j < std::size(spans); ++j) + assert((doAssign(spans[i], spans[j]))); + } +} diff --git a/libcxx/test/std/containers/views/span.cons/container.fail.cpp b/libcxx/test/std/containers/views/span.cons/container.fail.cpp new file mode 100644 index 00000000000..ecd7fcb91b8 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/container.fail.cpp @@ -0,0 +1,117 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, 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: +// — 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 <list> +#include <forward_list> +#include <deque> + +#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;} +}; + + +int main () +{ + +// Missing size and/or data + { + std::span<int> s1{IsAContainer<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span<int, 0> s2{IsAContainer<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + std::span<int> s3{NotAContainerNoData<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span<int, 0> s4{NotAContainerNoData<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + std::span<int> s5{NotAContainerNoSize<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span<int, 0> s6{NotAContainerNoSize<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + std::span<int> s7{NotAContainerPrivate<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span<int, 0> s8{NotAContainerPrivate<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + +// Again with the standard containers + std::span<int> s11{std::deque<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span<int, 0> s12{std::deque<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + std::span<int> s13{std::list<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span<int, 0> s14{std::list<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + std::span<int> s15{std::forward_list<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span<int, 0> s16{std::forward_list<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + } + +// Not the same type + { + std::span<float> s1{IsAContainer<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<float>'}} + std::span<float, 0> s2{IsAContainer<int>()}; // expected-error {{no matching constructor for initialization of 'std::span<float, 0>'}} + } + +// CV wrong (dynamically sized) + { + std::span< int> s1{IsAContainer<const int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span< int> s2{IsAContainer< volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span< int> s3{IsAContainer<const volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span<const int> s4{IsAContainer< volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}} + std::span<const int> s5{IsAContainer<const volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}} + std::span< volatile int> s6{IsAContainer<const int>()}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}} + std::span< volatile int> s7{IsAContainer<const volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}} + } + +// CV wrong (statically sized) + { + std::span< int,1> s1{IsAContainer<const int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}} + std::span< int,1> s2{IsAContainer< volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}} + std::span< int,1> s3{IsAContainer<const volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<int, 1>'}} + std::span<const int,1> s4{IsAContainer< volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 1>'}} + std::span<const int,1> s5{IsAContainer<const volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 1>'}} + std::span< volatile int,1> s6{IsAContainer<const int>()}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 1>'}} + std::span< volatile int,1> s7{IsAContainer<const volatile int>()}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 1>'}} + } + +} diff --git a/libcxx/test/std/containers/views/span.cons/container.pass.cpp b/libcxx/test/std/containers/views/span.cons/container.pass.cpp new file mode 100644 index 00000000000..478a3dac5db --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/container.pass.cpp @@ -0,0 +1,118 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, 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: +// — 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 const *getV() const {return &v_;} // for checking + T v_; +}; + + +void checkCV() +{ + std::vector<int> v = {1,2,3}; + +// Types the same (dynamic sized) + { + std::span< int> s1{v}; // a span< int> pointing at int. + } + +// Types the same (static sized) + { + std::span< int,3> s1{v}; // a span< int> pointing at int. + } + +// types different (dynamic sized) + { + 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. + } + +// types different (static sized) + { + std::span<const int,3> s1{v}; // a span<const int> pointing at int. + std::span< volatile int,3> s2{v}; // a span< volatile int> pointing at int. + std::span< volatile int,3> s3{v}; // a span< volatile int> pointing at const int. + std::span<const volatile int,3> s4{v}; // a span<const volatile int> pointing at int. + } +} + + +template <typename T> +constexpr bool testConstexprSpan() +{ + constexpr IsAContainer<const T> val{}; + std::span<const T> s1{val}; + std::span<const T, 1> s2{val}; + return + s1.data() == val.getV() && s1.size() == 1 + && s2.data() == val.getV() && s2.size() == 1; +} + + +template <typename T> +void testRuntimeSpan() +{ + IsAContainer<T> val{}; + std::span<const T> s1{val}; + std::span<const T, 1> s2{val}; + assert(s1.data() == val.getV() && s1.size() == 1); + assert(s2.data() == val.getV() && s2.size() == 1); +} + +struct A{}; + +int main () +{ + 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(); +} diff --git a/libcxx/test/std/containers/views/span.cons/copy.pass.cpp b/libcxx/test/std/containers/views/span.cons/copy.pass.cpp new file mode 100644 index 00000000000..2cfffbbd449 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/copy.pass.cpp @@ -0,0 +1,71 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr span(const span& other) noexcept = default; + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +template <typename T> +constexpr bool doCopy(const T &rhs) +{ + ASSERT_NOEXCEPT(T{rhs}); + T lhs{rhs}; + return lhs.data() == rhs.data() + && lhs.size() == rhs.size(); +} + +struct A{}; + +template <typename T> +void testCV () +{ + int arr[] = {1,2,3}; + assert((doCopy(std::span<T> () ))); + assert((doCopy(std::span<T,0>() ))); + assert((doCopy(std::span<T> (&arr[0], 1)))); + assert((doCopy(std::span<T,1>(&arr[0], 1)))); + assert((doCopy(std::span<T> (&arr[0], 2)))); + assert((doCopy(std::span<T,2>(&arr[0], 2)))); +} + + +int main () +{ + constexpr int carr[] = {1,2,3}; + + static_assert(doCopy(std::span< int> ()), ""); + static_assert(doCopy(std::span< int,0>()), ""); + static_assert(doCopy(std::span<const int> (&carr[0], 1)), ""); + static_assert(doCopy(std::span<const int,1>(&carr[0], 1)), ""); + static_assert(doCopy(std::span<const int> (&carr[0], 2)), ""); + static_assert(doCopy(std::span<const int,2>(&carr[0], 2)), ""); + + static_assert(doCopy(std::span<long>()), ""); + static_assert(doCopy(std::span<double>()), ""); + static_assert(doCopy(std::span<A>()), ""); + + std::string s; + assert(doCopy(std::span<std::string> () )); + assert(doCopy(std::span<std::string, 0>() )); + assert(doCopy(std::span<std::string> (&s, 1))); + assert(doCopy(std::span<std::string, 1>(&s, 1))); + + testCV< int>(); + testCV<const int>(); + testCV< volatile int>(); + testCV<const volatile int>(); +} diff --git a/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp b/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp new file mode 100644 index 00000000000..3410bb31c39 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/deduct.pass.cpp @@ -0,0 +1,83 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class T, size_t N> +// span(T (&)[N]) -> span<T, N>; +// +// template<class T, size_t N> +// span(array<T, N>&) -> span<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>; + + + +#include <span> +#include <algorithm> +#include <array> +#include <cassert> +#include <string> +#include <type_traits> + +#include "test_macros.h" + +int main () +{ + { + int arr[] = {1,2,3}; + std::span s{arr}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span<int, 3>); + assert((std::equal(std::begin(arr), std::end(arr), s.begin(), s.end()))); + } + + { + std::array<double, 4> arr = {1.0, 2.0, 3.0, 4.0}; + std::span s{arr}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span<double, 4>); + assert((std::equal(std::begin(arr), std::end(arr), s.begin(), s.end()))); + } + + { + const std::array<long, 5> arr = {4, 5, 6, 7, 8}; + std::span s{arr}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span<const long, 5>); + assert((std::equal(std::begin(arr), std::end(arr), s.begin(), s.end()))); + } + + { + std::string str{"ABCDE"}; + std::span s{str}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span<char>); + assert((size_t)s.size() == str.size()); + assert((std::equal(s.begin(), s.end(), std::begin(s), std::end(s)))); + } + + { + const std::string str{"QWERTYUIOP"}; + std::span s{str}; + using S = decltype(s); + ASSERT_SAME_TYPE(S, std::span<const char>); + assert((size_t)s.size() == str.size()); + assert((std::equal(s.begin(), s.end(), std::begin(s), std::end(s)))); + } +} diff --git a/libcxx/test/std/containers/views/span.cons/default.fail.cpp b/libcxx/test/std/containers/views/span.cons/default.fail.cpp new file mode 100644 index 00000000000..d1fefe5b38c --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/default.fail.cpp @@ -0,0 +1,32 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr span() noexcept; +// +// Remarks: This constructor shall not participate in overload resolution +// unless Extent <= 0 is true. + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +int main () +{ + std::span<int, 2> s; // expected-error@span:* {{static_assert failed "Can't default construct a statically sized span with size > 0"}} + +// TODO: This is what I want: +// eXpected-error {{no matching constructor for initialization of 'std::span<int, 2>'}} +} diff --git a/libcxx/test/std/containers/views/span.cons/default.pass.cpp b/libcxx/test/std/containers/views/span.cons/default.pass.cpp new file mode 100644 index 00000000000..f7e496696e9 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/default.pass.cpp @@ -0,0 +1,82 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr span() noexcept; + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +void checkCV() +{ +// Types the same (dynamic sized) + { + std::span< int> s1; + std::span<const int> s2; + std::span< volatile int> s3; + std::span<const volatile int> s4; + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } + +// Types the same (static sized) + { + std::span< int,0> s1; + std::span<const int,0> s2; + std::span< volatile int,0> s3; + std::span<const volatile int,0> s4; + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } +} + + +template <typename T> +constexpr bool testConstexprSpan() +{ + std::span<const T> s1; + std::span<const T, 0> s2; + return + s1.data() == nullptr && s1.size() == 0 + && s2.data() == nullptr && s2.size() == 0; +} + + +template <typename T> +void testRuntimeSpan() +{ + ASSERT_NOEXCEPT(T{}); + std::span<const T> s1; + std::span<const T, 0> s2; + assert(s1.data() == nullptr && s1.size() == 0); + assert(s2.data() == nullptr && s2.size() == 0); +} + + +struct A{}; + +int main () +{ + 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(); +} diff --git a/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp b/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp new file mode 100644 index 00000000000..db24e3d2688 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/ptr_len.fail.cpp @@ -0,0 +1,63 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr span(pointer ptr, index_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}; + +int main () +{ +// 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>'}} + } +} diff --git a/libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp b/libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp new file mode 100644 index 00000000000..7302759bcc6 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/ptr_len.pass.cpp @@ -0,0 +1,113 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr span(pointer ptr, index_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 () +{ + 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(); +} diff --git a/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp b/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp new file mode 100644 index 00000000000..a55f0592a08 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/ptr_ptr.fail.cpp @@ -0,0 +1,63 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, 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}; + +int main () +{ +// 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>'}} + } +} diff --git a/libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp b/libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp new file mode 100644 index 00000000000..afb525e7368 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/ptr_ptr.pass.cpp @@ -0,0 +1,113 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, 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 () +{ + 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(); +} diff --git a/libcxx/test/std/containers/views/span.cons/span.fail.cpp b/libcxx/test/std/containers/views/span.cons/span.fail.cpp new file mode 100644 index 00000000000..1fa71551b49 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/span.fail.cpp @@ -0,0 +1,104 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class OtherElementType, ptrdiff_t OtherExtent> +// constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept; +// +// Remarks: This constructor shall not participate in overload resolution unless: +// Extent == dynamic_extent || Extent == OtherExtent is true, and +// OtherElementType(*)[] is convertible to ElementType(*)[]. + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +void checkCV () +{ +// std::span< int> sp; + std::span<const int> csp; + std::span< volatile int> vsp; + std::span<const volatile int> cvsp; + +// std::span< int, 0> sp0; + std::span<const int, 0> csp0; + std::span< volatile int, 0> vsp0; + std::span<const volatile int, 0> cvsp0; + +// Try to remove const and/or volatile (dynamic -> dynamic) + { + std::span< int> s1{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span< int> s2{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span< int> s3{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + + std::span<const int> s4{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}} + std::span<const int> s5{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}} + + std::span< volatile int> s6{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}} + std::span< volatile int> s7{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}} + } + +// Try to remove const and/or volatile (static -> static) + { + std::span< int, 0> s1{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + std::span< int, 0> s2{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + std::span< int, 0> s3{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + + std::span<const int, 0> s4{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}} + std::span<const int, 0> s5{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}} + + std::span< volatile int, 0> s6{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}} + std::span< volatile int, 0> s7{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}} + } + +// Try to remove const and/or volatile (static -> dynamic) + { + std::span< int> s1{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span< int> s2{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + std::span< int> s3{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<int>'}} + + std::span<const int> s4{ vsp0}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}} + std::span<const int> s5{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<const int>'}} + + std::span< volatile int> s6{ csp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}} + std::span< volatile int> s7{cvsp0}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int>'}} + } + +// Try to remove const and/or volatile (static -> static) + { + std::span< int, 0> s1{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + std::span< int, 0> s2{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + std::span< int, 0> s3{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<int, 0>'}} + + std::span<const int, 0> s4{ vsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}} + std::span<const int, 0> s5{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<const int, 0>'}} + + std::span< volatile int, 0> s6{ csp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}} + std::span< volatile int, 0> s7{cvsp}; // expected-error {{no matching constructor for initialization of 'std::span<volatile int, 0>'}} + } +} + +int main () +{ + std::span<int> sp; + std::span<int, 0> sp0; + + std::span<float> s1{sp}; // expected-error {{no matching constructor for initialization of 'std::span<float>'}} + std::span<float> s2{sp0}; // expected-error {{no matching constructor for initialization of 'std::span<float>'}} + std::span<float, 0> s3{sp}; // expected-error {{no matching constructor for initialization of 'std::span<float, 0>'}} + std::span<float, 0> s4{sp0}; // expected-error {{no matching constructor for initialization of 'std::span<float, 0>'}} + + checkCV(); +} diff --git a/libcxx/test/std/containers/views/span.cons/span.pass.cpp b/libcxx/test/std/containers/views/span.cons/span.pass.cpp new file mode 100644 index 00000000000..b2024ce123c --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/span.pass.cpp @@ -0,0 +1,142 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class OtherElementType, ptrdiff_t OtherExtent> +// constexpr span(const span<OtherElementType, OtherExtent>& s) noexcept; +// +// Remarks: This constructor shall not participate in overload resolution unless: +// Extent == dynamic_extent || Extent == OtherExtent is true, and +// OtherElementType(*)[] is convertible to ElementType(*)[]. + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +void checkCV() +{ + std::span< int> sp; +// std::span<const int> csp; + std::span< volatile int> vsp; +// std::span<const volatile int> cvsp; + + std::span< int, 0> sp0; +// std::span<const int, 0> csp0; + std::span< volatile int, 0> vsp0; +// std::span<const volatile int, 0> cvsp0; + +// dynamic -> dynamic + { + std::span<const int> s1{ sp}; // a span<const int> pointing at int. + std::span< volatile int> s2{ sp}; // a span< volatile int> pointing at int. + std::span<const volatile int> s3{ sp}; // a span<const volatile int> pointing at int. + std::span<const volatile int> s4{ vsp}; // a span<const volatile int> pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } + +// static -> static + { + std::span<const int, 0> s1{ sp0}; // a span<const int> pointing at int. + std::span< volatile int, 0> s2{ sp0}; // a span< volatile int> pointing at int. + std::span<const volatile int, 0> s3{ sp0}; // a span<const volatile int> pointing at int. + std::span<const volatile int, 0> s4{ vsp0}; // a span<const volatile int> pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } + +// static -> dynamic + { + std::span<const int> s1{ sp0}; // a span<const int> pointing at int. + std::span< volatile int> s2{ sp0}; // a span< volatile int> pointing at int. + std::span<const volatile int> s3{ sp0}; // a span<const volatile int> pointing at int. + std::span<const volatile int> s4{ vsp0}; // a span<const volatile int> pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } + +// dynamic -> static + { + std::span<const int, 0> s1{ sp}; // a span<const int> pointing at int. + std::span< volatile int, 0> s2{ sp}; // a span< volatile int> pointing at int. + std::span<const volatile int, 0> s3{ sp}; // a span<const volatile int> pointing at int. + std::span<const volatile int, 0> s4{ vsp}; // a span<const volatile int> pointing at volatile int. + assert(s1.size() + s2.size() + s3.size() + s4.size() == 0); + } +} + + +template <typename T> +constexpr bool testConstexprSpan() +{ + std::span<T> s0{}; + std::span<T, 0> s1(s0); // dynamic -> static + std::span<T> s2(s1); // static -> dynamic + ASSERT_NOEXCEPT(std::span<T> {s0}); + ASSERT_NOEXCEPT(std::span<T, 0>{s1}); + ASSERT_NOEXCEPT(std::span<T> {s1}); + ASSERT_NOEXCEPT(std::span<T, 0>{s0}); + + return + s1.data() == nullptr && s1.size() == 0 + && s2.data() == nullptr && s2.size() == 0; +} + + +template <typename T> +void testRuntimeSpan() +{ + std::span<T> s0{}; + std::span<T, 0> s1(s0); // dynamic -> static + std::span<T> s2(s1); // static -> dynamic + ASSERT_NOEXCEPT(std::span<T> {s0}); + ASSERT_NOEXCEPT(std::span<T, 0>{s1}); + ASSERT_NOEXCEPT(std::span<T> {s1}); + ASSERT_NOEXCEPT(std::span<T, 0>{s0}); + + assert(s1.data() == nullptr && s1.size() == 0); + assert(s2.data() == nullptr && s2.size() == 0); +} + + +template <typename Dest, typename Src> +bool testConversionSpan() +{ + static_assert(std::is_convertible_v<Src(*)[], Dest(*)[]>, "Bad input types to 'testConversionSpan"); + std::span<Src> s0d{}; + std::span<Src> s0s{}; + std::span<Dest, 0> s1(s0d); // dynamic -> static + std::span<Dest> s2(s0s); // static -> dynamic + s1.data() == nullptr && s1.size() == 0 + && s2.data() == nullptr && s2.size() == 0; +} + +struct A{}; + +int main () +{ + 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>(); + +// TODO: Add some conversion tests here that aren't "X --> const X" +// assert((testConversionSpan<unsigned char, char>())); + + checkCV(); +} diff --git a/libcxx/test/std/containers/views/span.cons/stdarray.pass.cpp b/libcxx/test/std/containers/views/span.cons/stdarray.pass.cpp new file mode 100644 index 00000000000..204935db058 --- /dev/null +++ b/libcxx/test/std/containers/views/span.cons/stdarray.pass.cpp @@ -0,0 +1,111 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// 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; +// +// Remarks: These constructors shall not participate in overload resolution unless: +// — extent == dynamic_extent || N == extent is true, and +// — remove_pointer_t<decltype(data(arr))>(*)[] is convertible to ElementType(*)[]. +// + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + + +void checkCV() +{ + std::array<int, 3> arr = {1,2,3}; +// STL says these are not cromulent +// std::array<const int,3> carr = {4,5,6}; +// std::array<volatile int, 3> varr = {7,8,9}; +// std::array<const volatile int, 3> cvarr = {1,3,5}; + +// Types the same (dynamic sized) + { + std::span< int> s1{ arr}; // a span< int> pointing at int. + } + +// Types the same (static sized) + { + std::span< int,3> s1{ arr}; // a span< int> pointing at int. + } + + +// types different (dynamic sized) + { + std::span<const int> s1{ arr}; // a span<const int> pointing at int. + std::span< volatile int> s2{ arr}; // a span< volatile int> pointing at int. + std::span< volatile int> s3{ arr}; // a span< volatile int> pointing at const int. + std::span<const volatile int> s4{ arr}; // a span<const volatile int> pointing at int. + } + +// types different (static sized) + { + std::span<const int,3> s1{ arr}; // a span<const int> pointing at int. + std::span< volatile int,3> s2{ arr}; // a span< volatile int> pointing at int. + std::span< volatile int,3> s3{ arr}; // a span< volatile int> pointing at const int. + std::span<const volatile int,3> s4{ arr}; // a span<const volatile int> pointing at int. + } +} + + +template <typename T> +constexpr bool testConstexprSpan() +{ + constexpr std::array<T,2> val = { T(), T() }; + ASSERT_NOEXCEPT(std::span<const T> {val}); + ASSERT_NOEXCEPT(std::span<const T, 2>{val}); + std::span<const T> s1{val}; + std::span<const T, 2> s2{val}; + return + s1.data() == &val[0] && s1.size() == 2 + && s2.data() == &val[0] && s2.size() == 2; +} + + +template <typename T> +void testRuntimeSpan() +{ + std::array<T,2> val; + ASSERT_NOEXCEPT(std::span<T> {val}); + ASSERT_NOEXCEPT(std::span<T, 2>{val}); + std::span<T> s1{val}; + std::span<T, 2> s2{val}; + assert(s1.data() == &val[0] && s1.size() == 2); + assert(s2.data() == &val[0] && s2.size() == 2); +} + +struct A{}; + +int main () +{ + 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(); +} diff --git a/libcxx/test/std/containers/views/span.elem/data.pass.cpp b/libcxx/test/std/containers/views/span.elem/data.pass.cpp new file mode 100644 index 00000000000..3bc6fbbe576 --- /dev/null +++ b/libcxx/test/std/containers/views/span.elem/data.pass.cpp @@ -0,0 +1,121 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr pointer data() const noexcept; +// + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + + +template <typename Span> +constexpr bool testConstexprSpan(Span sp, typename Span::pointer ptr) +{ + ASSERT_NOEXCEPT(sp.data()); + return sp.data() == ptr; +} + + +template <typename Span> +void testRuntimeSpan(Span sp, typename Span::pointer ptr) +{ + ASSERT_NOEXCEPT(sp.data()); + assert(sp.data() == ptr); +} + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + +// dynamic size + static_assert(testConstexprSpan(std::span<int>(), nullptr), ""); + static_assert(testConstexprSpan(std::span<long>(), nullptr), ""); + static_assert(testConstexprSpan(std::span<double>(), nullptr), ""); + static_assert(testConstexprSpan(std::span<A>(), nullptr), ""); + static_assert(testConstexprSpan(std::span<std::string>(), nullptr), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), iArr1), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), iArr1), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), iArr1), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), iArr1), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1 + 1, 1), iArr1 + 1), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1 + 2, 2), iArr1 + 2), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1 + 3, 3), iArr1 + 3), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1 + 4, 4), iArr1 + 4), ""); + +// static size + static_assert(testConstexprSpan(std::span<int, 0>(), nullptr), ""); + static_assert(testConstexprSpan(std::span<long, 0>(), nullptr), ""); + static_assert(testConstexprSpan(std::span<double, 0>(), nullptr), ""); + static_assert(testConstexprSpan(std::span<A, 0>(), nullptr), ""); + static_assert(testConstexprSpan(std::span<std::string, 0>(), nullptr), ""); + + static_assert(testConstexprSpan(std::span<const int, 1>(iArr1, 1), iArr1), ""); + static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), iArr1), ""); + static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), iArr1), ""); + static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), iArr1), ""); + + static_assert(testConstexprSpan(std::span<const int, 1>(iArr1 + 1, 1), iArr1 + 1), ""); + static_assert(testConstexprSpan(std::span<const int, 2>(iArr1 + 2, 2), iArr1 + 2), ""); + static_assert(testConstexprSpan(std::span<const int, 3>(iArr1 + 3, 3), iArr1 + 3), ""); + static_assert(testConstexprSpan(std::span<const int, 4>(iArr1 + 4, 4), iArr1 + 4), ""); + + +// dynamic size + testRuntimeSpan(std::span<int>(), nullptr); + testRuntimeSpan(std::span<long>(), nullptr); + testRuntimeSpan(std::span<double>(), nullptr); + testRuntimeSpan(std::span<A>(), nullptr); + testRuntimeSpan(std::span<std::string>(), nullptr); + + testRuntimeSpan(std::span<int>(iArr2, 1), iArr2); + testRuntimeSpan(std::span<int>(iArr2, 2), iArr2); + testRuntimeSpan(std::span<int>(iArr2, 3), iArr2); + testRuntimeSpan(std::span<int>(iArr2, 4), iArr2); + + testRuntimeSpan(std::span<int>(iArr2 + 1, 1), iArr2 + 1); + testRuntimeSpan(std::span<int>(iArr2 + 2, 2), iArr2 + 2); + testRuntimeSpan(std::span<int>(iArr2 + 3, 3), iArr2 + 3); + testRuntimeSpan(std::span<int>(iArr2 + 4, 4), iArr2 + 4); + +// static size + testRuntimeSpan(std::span<int, 0>(), nullptr); + testRuntimeSpan(std::span<long, 0>(), nullptr); + testRuntimeSpan(std::span<double, 0>(), nullptr); + testRuntimeSpan(std::span<A, 0>(), nullptr); + testRuntimeSpan(std::span<std::string, 0>(), nullptr); + + testRuntimeSpan(std::span<int, 1>(iArr2, 1), iArr2); + testRuntimeSpan(std::span<int, 2>(iArr2, 2), iArr2); + testRuntimeSpan(std::span<int, 3>(iArr2, 3), iArr2); + testRuntimeSpan(std::span<int, 4>(iArr2, 4), iArr2); + + testRuntimeSpan(std::span<int, 1>(iArr2 + 1, 1), iArr2 + 1); + testRuntimeSpan(std::span<int, 2>(iArr2 + 2, 2), iArr2 + 2); + testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3), iArr2 + 3); + testRuntimeSpan(std::span<int, 4>(iArr2 + 4, 4), iArr2 + 4); + + + std::string s; + testRuntimeSpan(std::span<std::string>(&s, 1), &s); + testRuntimeSpan(std::span<std::string, 1>(&s, 1), &s); + +} diff --git a/libcxx/test/std/containers/views/span.elem/op_idx.pass.cpp b/libcxx/test/std/containers/views/span.elem/op_idx.pass.cpp new file mode 100644 index 00000000000..a88f4410427 --- /dev/null +++ b/libcxx/test/std/containers/views/span.elem/op_idx.pass.cpp @@ -0,0 +1,119 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr reference operator[](index_type idx) const; +// constexpr reference operator()(index_type idx) const; +// + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + + +template <typename Span> +constexpr bool testConstexprSpan(Span sp, ptrdiff_t idx) +{ + _LIBCPP_ASSERT(noexcept(sp[idx]), ""); + _LIBCPP_ASSERT(noexcept(sp(idx)), ""); + + typename Span::reference r1 = sp[idx]; + typename Span::reference r2 = sp(idx); + typename Span::reference r3 = *(sp.data() + idx); + return r1 == r2 && r2 == r3; +} + + +template <typename Span> +void testRuntimeSpan(Span sp, ptrdiff_t idx) +{ + _LIBCPP_ASSERT(noexcept(sp[idx]), ""); + _LIBCPP_ASSERT(noexcept(sp(idx)), ""); + + typename Span::reference r1 = sp[idx]; + typename Span::reference r2 = sp(idx); + typename Span::reference r3 = *(sp.data() + idx); + assert(r1 == r2 && r2 == r3); +} + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), 0), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 0), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 1), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 0), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 1), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 2), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 0), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 1), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 2), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 3), ""); + + + static_assert(testConstexprSpan(std::span<const int, 1>(iArr1, 1), 0), ""); + + static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), 0), ""); + static_assert(testConstexprSpan(std::span<const int, 2>(iArr1, 2), 1), ""); + + static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 0), ""); + static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 1), ""); + static_assert(testConstexprSpan(std::span<const int, 3>(iArr1, 3), 2), ""); + + static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 0), ""); + static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 1), ""); + static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 2), ""); + static_assert(testConstexprSpan(std::span<const int, 4>(iArr1, 4), 3), ""); + + + testRuntimeSpan(std::span<int>(iArr2, 1), 0); + + testRuntimeSpan(std::span<int>(iArr2, 2), 0); + testRuntimeSpan(std::span<int>(iArr2, 2), 1); + + testRuntimeSpan(std::span<int>(iArr2, 3), 0); + testRuntimeSpan(std::span<int>(iArr2, 3), 1); + testRuntimeSpan(std::span<int>(iArr2, 3), 2); + + testRuntimeSpan(std::span<int>(iArr2, 4), 0); + testRuntimeSpan(std::span<int>(iArr2, 4), 1); + testRuntimeSpan(std::span<int>(iArr2, 4), 2); + testRuntimeSpan(std::span<int>(iArr2, 4), 3); + + + testRuntimeSpan(std::span<int, 1>(iArr2, 1), 0); + + testRuntimeSpan(std::span<int, 2>(iArr2, 2), 0); + testRuntimeSpan(std::span<int, 2>(iArr2, 2), 1); + + testRuntimeSpan(std::span<int, 3>(iArr2, 3), 0); + testRuntimeSpan(std::span<int, 3>(iArr2, 3), 1); + testRuntimeSpan(std::span<int, 3>(iArr2, 3), 2); + + testRuntimeSpan(std::span<int, 4>(iArr2, 4), 0); + testRuntimeSpan(std::span<int, 4>(iArr2, 4), 1); + testRuntimeSpan(std::span<int, 4>(iArr2, 4), 2); + testRuntimeSpan(std::span<int, 4>(iArr2, 4), 3); + + std::string s; + testRuntimeSpan(std::span<std::string> (&s, 1), 0); + testRuntimeSpan(std::span<std::string, 1>(&s, 1), 0); +} diff --git a/libcxx/test/std/containers/views/span.iterators/begin.pass.cpp b/libcxx/test/std/containers/views/span.iterators/begin.pass.cpp new file mode 100644 index 00000000000..c8b9900bc15 --- /dev/null +++ b/libcxx/test/std/containers/views/span.iterators/begin.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr iterator begin() const noexcept; +// constexpr const_iterator cbegin() const noexcept; + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +template <class Span> +constexpr bool testConstexprSpan(Span s) +{ + bool ret = true; + typename Span::iterator b = s. begin(); + typename Span::const_iterator cb = s.cbegin(); + + if (s.empty()) + { + ret = ret && ( b == s.end()); + ret = ret && (cb == s.cend()); + } + else + { + ret = ret && ( *b == s[0]); + ret = ret && ( &*b == &s[0]); + ret = ret && ( *cb == s[0]); + ret = ret && (&*cb == &s[0]); + } + ret = ret && (b == cb); + return ret; +} + + +template <class Span> +void testRuntimeSpan(Span s) +{ + typename Span::iterator b = s. begin(); + typename Span::const_iterator cb = s.cbegin(); + + if (s.empty()) + { + assert( b == s.end()); + assert(cb == s.cend()); + } + else + { + assert( *b == s[0]); + assert( &*b == &s[0]); + assert( *cb == s[0]); + assert(&*cb == &s[0]); + } + assert(b == cb); +} + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + +int main() +{ + static_assert(testConstexprSpan(std::span<int>()), ""); + static_assert(testConstexprSpan(std::span<long>()), ""); + static_assert(testConstexprSpan(std::span<double>()), ""); + static_assert(testConstexprSpan(std::span<A>()), ""); + static_assert(testConstexprSpan(std::span<std::string>()), ""); + + static_assert(testConstexprSpan(std::span<int, 0>()), ""); + static_assert(testConstexprSpan(std::span<long, 0>()), ""); + static_assert(testConstexprSpan(std::span<double, 0>()), ""); + static_assert(testConstexprSpan(std::span<A, 0>()), ""); + static_assert(testConstexprSpan(std::span<std::string, 0>()), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 5)), ""); + + + testRuntimeSpan(std::span<int> ()); + testRuntimeSpan(std::span<long> ()); + testRuntimeSpan(std::span<double> ()); + testRuntimeSpan(std::span<A> ()); + testRuntimeSpan(std::span<std::string>()); + + testRuntimeSpan(std::span<int, 0> ()); + testRuntimeSpan(std::span<long, 0> ()); + testRuntimeSpan(std::span<double, 0> ()); + testRuntimeSpan(std::span<A, 0> ()); + testRuntimeSpan(std::span<std::string, 0>()); + + testRuntimeSpan(std::span<int>(iArr2, 1)); + testRuntimeSpan(std::span<int>(iArr2, 2)); + testRuntimeSpan(std::span<int>(iArr2, 3)); + testRuntimeSpan(std::span<int>(iArr2, 4)); + testRuntimeSpan(std::span<int>(iArr2, 5)); + + std::string s; + testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span<std::string>(&s, 1)); +} diff --git a/libcxx/test/std/containers/views/span.iterators/end.pass.cpp b/libcxx/test/std/containers/views/span.iterators/end.pass.cpp new file mode 100644 index 00000000000..2b64b0f4b54 --- /dev/null +++ b/libcxx/test/std/containers/views/span.iterators/end.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr iterator end() const noexcept; +// constexpr const_iterator cend() const noexcept; + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +template <class Span> +constexpr bool testConstexprSpan(Span s) +{ + bool ret = true; + typename Span::iterator e = s. end(); + typename Span::const_iterator ce = s.cend(); + if (s.empty()) + { + ret = ret && ( e == s.begin()); + ret = ret && (ce == s.cbegin()); + } + else + { + ret = ret && ( e != s.begin()); + ret = ret && (ce != s.cbegin()); + } + + ret = ret && (( e - s.begin()) == s.size()); + ret = ret && ((ce - s.cbegin()) == s.size()); + + ret = ret && (e == ce); + return ret; +} + +template <class Span> +void testRuntimeSpan(Span s) +{ + typename Span::iterator e = s. end(); + typename Span::const_iterator ce = s.cend(); + if (s.empty()) + { + assert( e == s.begin()); + assert(ce == s.cbegin()); + } + else + { + assert( e != s.begin()); + assert(ce != s.cbegin()); + } + + assert(( e - s.begin()) == s.size()); + assert((ce - s.cbegin()) == s.size()); + + assert(e == ce); +} + + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + +int main() +{ + static_assert(testConstexprSpan(std::span<int>()), ""); + static_assert(testConstexprSpan(std::span<long>()), ""); + static_assert(testConstexprSpan(std::span<double>()), ""); + static_assert(testConstexprSpan(std::span<A>()), ""); + static_assert(testConstexprSpan(std::span<std::string>()), ""); + + static_assert(testConstexprSpan(std::span<int, 0>()), ""); + static_assert(testConstexprSpan(std::span<long, 0>()), ""); + static_assert(testConstexprSpan(std::span<double, 0>()), ""); + static_assert(testConstexprSpan(std::span<A, 0>()), ""); + static_assert(testConstexprSpan(std::span<std::string, 0>()), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 5)), ""); + + + testRuntimeSpan(std::span<int> ()); + testRuntimeSpan(std::span<long> ()); + testRuntimeSpan(std::span<double> ()); + testRuntimeSpan(std::span<A> ()); + testRuntimeSpan(std::span<std::string>()); + + testRuntimeSpan(std::span<int, 0> ()); + testRuntimeSpan(std::span<long, 0> ()); + testRuntimeSpan(std::span<double, 0> ()); + testRuntimeSpan(std::span<A, 0> ()); + testRuntimeSpan(std::span<std::string, 0>()); + + testRuntimeSpan(std::span<int>(iArr2, 1)); + testRuntimeSpan(std::span<int>(iArr2, 2)); + testRuntimeSpan(std::span<int>(iArr2, 3)); + testRuntimeSpan(std::span<int>(iArr2, 4)); + testRuntimeSpan(std::span<int>(iArr2, 5)); + + std::string s; + testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span<std::string>(&s, 1)); +} diff --git a/libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp b/libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp new file mode 100644 index 00000000000..c0776c00a81 --- /dev/null +++ b/libcxx/test/std/containers/views/span.iterators/rbegin.pass.cpp @@ -0,0 +1,117 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr reverse_iterator rbegin() const noexcept; +// constexpr const_reverse_iterator crbegin() const noexcept; + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +template <class Span> +constexpr bool testConstexprSpan(Span s) +{ + bool ret = true; + typename Span::reverse_iterator b = s. rbegin(); + typename Span::const_reverse_iterator cb = s.crbegin(); + if (s.empty()) + { + ret = ret && ( b == s.rend()); + ret = ret && (cb == s.crend()); + } + else + { + const typename Span::index_type last = s.size() - 1; + ret = ret && ( *b == s[last]); + ret = ret && ( &*b == &s[last]); + ret = ret && ( *cb == s[last]); + ret = ret && (&*cb == &s[last]); + } + ret = ret && (b == cb); + return ret; +} + + +template <class Span> +void testRuntimeSpan(Span s) +{ + typename Span::reverse_iterator b = s. rbegin(); + typename Span::const_reverse_iterator cb = s.crbegin(); + if (s.empty()) + { + assert( b == s.rend()); + assert(cb == s.crend()); + } + else + { + const typename Span::index_type last = s.size() - 1; + assert( *b == s[last]); + assert( &*b == &s[last]); + assert( *cb == s[last]); + assert(&*cb == &s[last]); + } + assert(b == cb); +} + + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + +int main() +{ + static_assert(testConstexprSpan(std::span<int>()), ""); + static_assert(testConstexprSpan(std::span<long>()), ""); + static_assert(testConstexprSpan(std::span<double>()), ""); + static_assert(testConstexprSpan(std::span<A>()), ""); + static_assert(testConstexprSpan(std::span<std::string>()), ""); + + static_assert(testConstexprSpan(std::span<int, 0>()), ""); + static_assert(testConstexprSpan(std::span<long, 0>()), ""); + static_assert(testConstexprSpan(std::span<double, 0>()), ""); + static_assert(testConstexprSpan(std::span<A, 0>()), ""); + static_assert(testConstexprSpan(std::span<std::string, 0>()), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 5)), ""); + + + testRuntimeSpan(std::span<int> ()); + testRuntimeSpan(std::span<long> ()); + testRuntimeSpan(std::span<double> ()); + testRuntimeSpan(std::span<A> ()); + testRuntimeSpan(std::span<std::string>()); + + testRuntimeSpan(std::span<int, 0> ()); + testRuntimeSpan(std::span<long, 0> ()); + testRuntimeSpan(std::span<double, 0> ()); + testRuntimeSpan(std::span<A, 0> ()); + testRuntimeSpan(std::span<std::string, 0>()); + + testRuntimeSpan(std::span<int>(iArr2, 1)); + testRuntimeSpan(std::span<int>(iArr2, 2)); + testRuntimeSpan(std::span<int>(iArr2, 3)); + testRuntimeSpan(std::span<int>(iArr2, 4)); + testRuntimeSpan(std::span<int>(iArr2, 5)); + + std::string s; + testRuntimeSpan(std::span<std::string>(&s, static_cast<std::ptrdiff_t>(0))); + testRuntimeSpan(std::span<std::string>(&s, 1)); +} diff --git a/libcxx/test/std/containers/views/span.iterators/rend.pass.cpp b/libcxx/test/std/containers/views/span.iterators/rend.pass.cpp new file mode 100644 index 00000000000..abcead445e1 --- /dev/null +++ b/libcxx/test/std/containers/views/span.iterators/rend.pass.cpp @@ -0,0 +1,118 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr reverse_iterator rend() const noexcept; +// constexpr const_reverse_iterator crend() const noexcept; + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +template <class Span> +constexpr bool testConstexprSpan(Span s) +{ + bool ret = true; + typename Span::reverse_iterator e = s. rend(); + typename Span::const_reverse_iterator ce = s.crend(); + if (s.empty()) + { + ret = ret && ( e == s.rbegin()); + ret = ret && (ce == s.crbegin()); + } + else + { + ret = ret && ( e != s.rbegin()); + ret = ret && (ce != s.crbegin()); + } + + ret = ret && (( e - s.rbegin()) == s.size()); + ret = ret && ((ce - s.crbegin()) == s.size()); + + ret = ret && (e == ce); + return ret; +} + +template <class Span> +void testRuntimeSpan(Span s) +{ + typename Span::reverse_iterator e = s. rend(); + typename Span::const_reverse_iterator ce = s.crend(); + if (s.empty()) + { + assert( e == s.rbegin()); + assert(ce == s.crbegin()); + } + else + { + assert( e != s.rbegin()); + assert(ce != s.crbegin()); + } + + assert(( e - s.rbegin()) == s.size()); + assert((ce - s.crbegin()) == s.size()); + + assert(e == ce); +} + + +struct A{}; +bool operator==(A, A) {return true;} + +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + + +int main() +{ + static_assert(testConstexprSpan(std::span<int>()), ""); + static_assert(testConstexprSpan(std::span<long>()), ""); + static_assert(testConstexprSpan(std::span<double>()), ""); + static_assert(testConstexprSpan(std::span<A>()), ""); + static_assert(testConstexprSpan(std::span<std::string>()), ""); + + static_assert(testConstexprSpan(std::span<int, 0>()), ""); + static_assert(testConstexprSpan(std::span<long, 0>()), ""); + static_assert(testConstexprSpan(std::span<double, 0>()), ""); + static_assert(testConstexprSpan(std::span<A, 0>()), ""); + static_assert(testConstexprSpan(std::span<std::string, 0>()), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4)), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 5)), ""); + + + testRuntimeSpan(std::span<int> ()); + testRuntimeSpan(std::span<long> ()); + testRuntimeSpan(std::span<double> ()); + testRuntimeSpan(std::span<A> ()); + testRuntimeSpan(std::span<std::string>()); + + testRuntimeSpan(std::span<int, 0> ()); + testRuntimeSpan(std::span<long, 0> ()); + testRuntimeSpan(std::span<double, 0> ()); + testRuntimeSpan(std::span<A, 0> ()); + testRuntimeSpan(std::span<std::string, 0>()); + + testRuntimeSpan(std::span<int>(iArr2, 1)); + testRuntimeSpan(std::span<int>(iArr2, 2)); + testRuntimeSpan(std::span<int>(iArr2, 3)); + testRuntimeSpan(std::span<int>(iArr2, 4)); + testRuntimeSpan(std::span<int>(iArr2, 5)); + + std::string s; + testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span<std::string>(&s, 1)); +} diff --git a/libcxx/test/std/containers/views/span.objectrep/as_bytes.pass.cpp b/libcxx/test/std/containers/views/span.objectrep/as_bytes.pass.cpp new file mode 100644 index 00000000000..b081b95c373 --- /dev/null +++ b/libcxx/test/std/containers/views/span.objectrep/as_bytes.pass.cpp @@ -0,0 +1,78 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template <class ElementType, ptrdiff_t Extent> +// span<const byte, +// Extent == dynamic_extent +// ? dynamic_extent +// : static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent> +// as_bytes(span<ElementType, Extent> s) noexcept; + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +template<typename Span> +void testRuntimeSpan(Span sp) +{ + ASSERT_NOEXCEPT(std::as_bytes(sp)); + + auto spBytes = std::as_bytes(sp); + using SB = decltype(spBytes); + ASSERT_SAME_TYPE(const std::byte, typename SB::element_type); + + if (sp.extent == std::dynamic_extent) + assert(spBytes.extent == std::dynamic_extent); + else + assert(spBytes.extent == static_cast<std::ptrdiff_t>(sizeof(typename Span::element_type)) * sp.extent); + + assert((void *) spBytes.data() == (void *) sp.data()); + assert(spBytes.size() == sp.size_bytes()); +} + +struct A{}; +int iArr2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + +int main () +{ + testRuntimeSpan(std::span<int> ()); + testRuntimeSpan(std::span<long> ()); + testRuntimeSpan(std::span<double> ()); + testRuntimeSpan(std::span<A> ()); + testRuntimeSpan(std::span<std::string>()); + + testRuntimeSpan(std::span<int, 0> ()); + testRuntimeSpan(std::span<long, 0> ()); + testRuntimeSpan(std::span<double, 0> ()); + testRuntimeSpan(std::span<A, 0> ()); + testRuntimeSpan(std::span<std::string, 0>()); + + testRuntimeSpan(std::span<int>(iArr2, 1)); + testRuntimeSpan(std::span<int>(iArr2, 2)); + testRuntimeSpan(std::span<int>(iArr2, 3)); + testRuntimeSpan(std::span<int>(iArr2, 4)); + testRuntimeSpan(std::span<int>(iArr2, 5)); + + testRuntimeSpan(std::span<int, 1>(iArr2 + 5, 1)); + testRuntimeSpan(std::span<int, 2>(iArr2 + 4, 2)); + testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3)); + testRuntimeSpan(std::span<int, 4>(iArr2 + 2, 4)); + testRuntimeSpan(std::span<int, 5>(iArr2 + 1, 5)); + + std::string s; + testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span<std::string>(&s, 1)); +} diff --git a/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp b/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp new file mode 100644 index 00000000000..28a4c45d247 --- /dev/null +++ b/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.fail.cpp @@ -0,0 +1,48 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template <class ElementType, ptrdiff_t Extent> +// span<byte, +// Extent == dynamic_extent +// ? dynamic_extent +// : static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent> +// as_writeable_bytes(span<ElementType, Extent> s) noexcept; + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +const int iArr2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + +struct A {}; + +int main () +{ + std::as_writeable_bytes(std::span<const int>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span<const long>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span<const double>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span<const A>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span<const std::string>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + + std::as_writeable_bytes(std::span<const int, 0>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span<const long, 0>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span<const double, 0>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span<const A, 0>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span<const std::string, 0>()); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + + std::as_writeable_bytes(std::span<const int> (iArr2, 1)); // expected-error {{no matching function for call to 'as_writeable_bytes'}} + std::as_writeable_bytes(std::span<const int, 1>(iArr2 + 5, 1)); // expected-error {{no matching function for call to 'as_writeable_bytes'}} +} diff --git a/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp b/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp new file mode 100644 index 00000000000..24e3fb27349 --- /dev/null +++ b/libcxx/test/std/containers/views/span.objectrep/as_writeable_bytes.pass.cpp @@ -0,0 +1,78 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template <class ElementType, ptrdiff_t Extent> +// span<byte, +// Extent == dynamic_extent +// ? dynamic_extent +// : static_cast<ptrdiff_t>(sizeof(ElementType)) * Extent> +// as_writeable_bytes(span<ElementType, Extent> s) noexcept; + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +template<typename Span> +void testRuntimeSpan(Span sp) +{ + ASSERT_NOEXCEPT(std::as_writeable_bytes(sp)); + + auto spBytes = std::as_writeable_bytes(sp); + using SB = decltype(spBytes); + ASSERT_SAME_TYPE(std::byte, typename SB::element_type); + + if (sp.extent == std::dynamic_extent) + assert(spBytes.extent == std::dynamic_extent); + else + assert(spBytes.extent == static_cast<std::ptrdiff_t>(sizeof(typename Span::element_type)) * sp.extent); + + assert(static_cast<void*>(spBytes.data()) == static_cast<void*>(sp.data())); + assert(spBytes.size() == sp.size_bytes()); +} + +struct A{}; +int iArr2[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + +int main () +{ + testRuntimeSpan(std::span<int> ()); + testRuntimeSpan(std::span<long> ()); + testRuntimeSpan(std::span<double> ()); + testRuntimeSpan(std::span<A> ()); + testRuntimeSpan(std::span<std::string>()); + + testRuntimeSpan(std::span<int, 0> ()); + testRuntimeSpan(std::span<long, 0> ()); + testRuntimeSpan(std::span<double, 0> ()); + testRuntimeSpan(std::span<A, 0> ()); + testRuntimeSpan(std::span<std::string, 0>()); + + testRuntimeSpan(std::span<int>(iArr2, 1)); + testRuntimeSpan(std::span<int>(iArr2, 2)); + testRuntimeSpan(std::span<int>(iArr2, 3)); + testRuntimeSpan(std::span<int>(iArr2, 4)); + testRuntimeSpan(std::span<int>(iArr2, 5)); + + testRuntimeSpan(std::span<int, 1>(iArr2 + 5, 1)); + testRuntimeSpan(std::span<int, 2>(iArr2 + 4, 2)); + testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3)); + testRuntimeSpan(std::span<int, 4>(iArr2 + 2, 4)); + testRuntimeSpan(std::span<int, 5>(iArr2 + 1, 5)); + + std::string s; + testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0)); + testRuntimeSpan(std::span<std::string>(&s, 1)); +} diff --git a/libcxx/test/std/containers/views/span.obs/empty.pass.cpp b/libcxx/test/std/containers/views/span.obs/empty.pass.cpp new file mode 100644 index 00000000000..a48c0d02494 --- /dev/null +++ b/libcxx/test/std/containers/views/span.obs/empty.pass.cpp @@ -0,0 +1,73 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr bool empty() const noexcept; +// + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + static_assert( noexcept(std::span<int> ().empty()), ""); + static_assert( noexcept(std::span<int, 0>().empty()), ""); + + + static_assert( std::span<int>().empty(), ""); + static_assert( std::span<long>().empty(), ""); + static_assert( std::span<double>().empty(), ""); + static_assert( std::span<A>().empty(), ""); + static_assert( std::span<std::string>().empty(), ""); + + static_assert( std::span<int, 0>().empty(), ""); + static_assert( std::span<long, 0>().empty(), ""); + static_assert( std::span<double, 0>().empty(), ""); + static_assert( std::span<A, 0>().empty(), ""); + static_assert( std::span<std::string, 0>().empty(), ""); + + static_assert(!std::span<const int>(iArr1, 1).empty(), ""); + static_assert(!std::span<const int>(iArr1, 2).empty(), ""); + static_assert(!std::span<const int>(iArr1, 3).empty(), ""); + static_assert(!std::span<const int>(iArr1, 4).empty(), ""); + static_assert(!std::span<const int>(iArr1, 5).empty(), ""); + + assert( (std::span<int>().empty() )); + assert( (std::span<long>().empty() )); + assert( (std::span<double>().empty() )); + assert( (std::span<A>().empty() )); + assert( (std::span<std::string>().empty() )); + + assert( (std::span<int, 0>().empty() )); + assert( (std::span<long, 0>().empty() )); + assert( (std::span<double, 0>().empty() )); + assert( (std::span<A, 0>().empty() )); + assert( (std::span<std::string, 0>().empty())); + + assert(!(std::span<int, 1>(iArr2, 1).empty())); + assert(!(std::span<int, 2>(iArr2, 2).empty())); + assert(!(std::span<int, 3>(iArr2, 3).empty())); + assert(!(std::span<int, 4>(iArr2, 4).empty())); + assert(!(std::span<int, 5>(iArr2, 5).empty())); + + std::string s; + assert( ((std::span<std::string>(&s, (std::ptrdiff_t) 0)).empty())); + assert(!((std::span<std::string>(&s, 1).empty()))); +} diff --git a/libcxx/test/std/containers/views/span.obs/size.pass.cpp b/libcxx/test/std/containers/views/span.obs/size.pass.cpp new file mode 100644 index 00000000000..c33fd3f6c61 --- /dev/null +++ b/libcxx/test/std/containers/views/span.obs/size.pass.cpp @@ -0,0 +1,91 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr index_type size() const noexcept; +// + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + + +template <typename Span> +constexpr bool testConstexprSpan(Span sp, ptrdiff_t sz) +{ + ASSERT_NOEXCEPT(sp.size()); + return sp.size() == sz; +} + + +template <typename Span> +void testRuntimeSpan(Span sp, ptrdiff_t sz) +{ + ASSERT_NOEXCEPT(sp.size()); + assert(sp.size() == sz); +} + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + static_assert(testConstexprSpan(std::span<int>(), 0), ""); + static_assert(testConstexprSpan(std::span<long>(), 0), ""); + static_assert(testConstexprSpan(std::span<double>(), 0), ""); + static_assert(testConstexprSpan(std::span<A>(), 0), ""); + static_assert(testConstexprSpan(std::span<std::string>(), 0), ""); + + static_assert(testConstexprSpan(std::span<int, 0>(), 0), ""); + static_assert(testConstexprSpan(std::span<long, 0>(), 0), ""); + static_assert(testConstexprSpan(std::span<double, 0>(), 0), ""); + static_assert(testConstexprSpan(std::span<A, 0>(), 0), ""); + static_assert(testConstexprSpan(std::span<std::string, 0>(), 0), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), 1), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 2), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 3), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 4), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 5), 5), ""); + + testRuntimeSpan(std::span<int> (), 0); + testRuntimeSpan(std::span<long> (), 0); + testRuntimeSpan(std::span<double> (), 0); + testRuntimeSpan(std::span<A> (), 0); + testRuntimeSpan(std::span<std::string>(), 0); + + testRuntimeSpan(std::span<int, 0> (), 0); + testRuntimeSpan(std::span<long, 0> (), 0); + testRuntimeSpan(std::span<double, 0> (), 0); + testRuntimeSpan(std::span<A, 0> (), 0); + testRuntimeSpan(std::span<std::string, 0>(), 0); + + testRuntimeSpan(std::span<int>(iArr2, 1), 1); + testRuntimeSpan(std::span<int>(iArr2, 2), 2); + testRuntimeSpan(std::span<int>(iArr2, 3), 3); + testRuntimeSpan(std::span<int>(iArr2, 4), 4); + testRuntimeSpan(std::span<int>(iArr2, 5), 5); + + testRuntimeSpan(std::span<int, 1>(iArr2 + 5, 1), 1); + testRuntimeSpan(std::span<int, 2>(iArr2 + 4, 2), 2); + testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3), 3); + testRuntimeSpan(std::span<int, 4>(iArr2 + 2, 4), 4); + testRuntimeSpan(std::span<int, 5>(iArr2 + 1, 5), 5); + + std::string s; + testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0), 0); + testRuntimeSpan(std::span<std::string>(&s, 1), 1); +} diff --git a/libcxx/test/std/containers/views/span.obs/size_bytes.pass.cpp b/libcxx/test/std/containers/views/span.obs/size_bytes.pass.cpp new file mode 100644 index 00000000000..1ee75d9fcb7 --- /dev/null +++ b/libcxx/test/std/containers/views/span.obs/size_bytes.pass.cpp @@ -0,0 +1,92 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// constexpr index_type size_bytes() const noexcept; +// +// Effects: Equivalent to: return size() * sizeof(element_type); + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + + +template <typename Span> +constexpr bool testConstexprSpan(Span sp, ptrdiff_t sz) +{ + ASSERT_NOEXCEPT(sp.size_bytes()); + return (size_t) sp.size_bytes() == sz * sizeof(typename Span::element_type); +} + + +template <typename Span> +void testRuntimeSpan(Span sp, ptrdiff_t sz) +{ + ASSERT_NOEXCEPT(sp.size_bytes()); + assert((size_t) sp.size_bytes() == sz * sizeof(typename Span::element_type)); +} + +struct A{}; +constexpr int iArr1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + int iArr2[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19}; + +int main () +{ + static_assert(testConstexprSpan(std::span<int>(), 0), ""); + static_assert(testConstexprSpan(std::span<long>(), 0), ""); + static_assert(testConstexprSpan(std::span<double>(), 0), ""); + static_assert(testConstexprSpan(std::span<A>(), 0), ""); + static_assert(testConstexprSpan(std::span<std::string>(), 0), ""); + + static_assert(testConstexprSpan(std::span<int, 0>(), 0), ""); + static_assert(testConstexprSpan(std::span<long, 0>(), 0), ""); + static_assert(testConstexprSpan(std::span<double, 0>(), 0), ""); + static_assert(testConstexprSpan(std::span<A, 0>(), 0), ""); + static_assert(testConstexprSpan(std::span<std::string, 0>(), 0), ""); + + static_assert(testConstexprSpan(std::span<const int>(iArr1, 1), 1), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 2), 2), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 3), 3), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 4), 4), ""); + static_assert(testConstexprSpan(std::span<const int>(iArr1, 5), 5), ""); + + testRuntimeSpan(std::span<int> (), 0); + testRuntimeSpan(std::span<long> (), 0); + testRuntimeSpan(std::span<double> (), 0); + testRuntimeSpan(std::span<A> (), 0); + testRuntimeSpan(std::span<std::string>(), 0); + + testRuntimeSpan(std::span<int, 0> (), 0); + testRuntimeSpan(std::span<long, 0> (), 0); + testRuntimeSpan(std::span<double, 0> (), 0); + testRuntimeSpan(std::span<A, 0> (), 0); + testRuntimeSpan(std::span<std::string, 0>(), 0); + + testRuntimeSpan(std::span<int>(iArr2, 1), 1); + testRuntimeSpan(std::span<int>(iArr2, 2), 2); + testRuntimeSpan(std::span<int>(iArr2, 3), 3); + testRuntimeSpan(std::span<int>(iArr2, 4), 4); + testRuntimeSpan(std::span<int>(iArr2, 5), 5); + + testRuntimeSpan(std::span<int, 1>(iArr2 + 5, 1), 1); + testRuntimeSpan(std::span<int, 2>(iArr2 + 4, 2), 2); + testRuntimeSpan(std::span<int, 3>(iArr2 + 3, 3), 3); + testRuntimeSpan(std::span<int, 4>(iArr2 + 2, 4), 4); + testRuntimeSpan(std::span<int, 5>(iArr2 + 1, 5), 5); + + std::string s; + testRuntimeSpan(std::span<std::string>(&s, (std::ptrdiff_t) 0), 0); + testRuntimeSpan(std::span<std::string>(&s, 1), 1); +} diff --git a/libcxx/test/std/containers/views/span.sub/first.pass.cpp b/libcxx/test/std/containers/views/span.sub/first.pass.cpp new file mode 100644 index 00000000000..3bfdab9f8a5 --- /dev/null +++ b/libcxx/test/std/containers/views/span.sub/first.pass.cpp @@ -0,0 +1,136 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<ptrdiff_t Count> +// constexpr span<element_type, Count> first() const; +// +// constexpr span<element_type, dynamic_extent> first(index_type count) const; +// +// Requires: 0 <= Count && Count <= size(). + + +#include <span> +#include <cassert> +#include <algorithm> +#include <string> + +#include "test_macros.h" + +template <typename Span, ptrdiff_t Count> +constexpr bool testConstexprSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template first<Count>()))); + LIBCPP_ASSERT((noexcept(sp.first(Count)))); + auto s1 = sp.template first<Count>(); + auto s2 = sp.first(Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == Count, ""); + static_assert(S2::extent == std::dynamic_extent, ""); + return + s1.data() == s2.data() + && s1.size() == s2.size() + && std::equal(s1.begin(), s1.end(), sp.begin()); +} + + +template <typename Span, ptrdiff_t Count> +void testRuntimeSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template first<Count>()))); + LIBCPP_ASSERT((noexcept(sp.first(Count)))); + auto s1 = sp.template first<Count>(); + auto s2 = sp.first(Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == Count, ""); + static_assert(S2::extent == std::dynamic_extent, ""); + assert(s1.data() == s2.data()); + assert(s1.size() == s2.size()); + assert(std::equal(s1.begin(), s1.end(), sp.begin())); +} + + +constexpr int carr1[] = {1,2,3,4}; + int arr[] = {5,6,7}; +std::string sarr [] = { "ABC", "DEF", "GHI", "JKL", "MNO"}; + +int main () +{ + { + using Sp = std::span<const int>; + static_assert(testConstexprSpan<Sp, 0>(Sp{}), ""); + + static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); + } + + { + using Sp = std::span<const int, 4>; + + static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); + } + + { + using Sp = std::span<int>; + testRuntimeSpan<Sp, 0>(Sp{}); + + testRuntimeSpan<Sp, 0>(Sp{arr}); + testRuntimeSpan<Sp, 1>(Sp{arr}); + testRuntimeSpan<Sp, 2>(Sp{arr}); + testRuntimeSpan<Sp, 3>(Sp{arr}); + } + + { + using Sp = std::span<int, 3>; + + testRuntimeSpan<Sp, 0>(Sp{arr}); + testRuntimeSpan<Sp, 1>(Sp{arr}); + testRuntimeSpan<Sp, 2>(Sp{arr}); + testRuntimeSpan<Sp, 3>(Sp{arr}); + } + + { + using Sp = std::span<std::string>; + testConstexprSpan<Sp, 0>(Sp{}); + + testRuntimeSpan<Sp, 0>(Sp{sarr}); + testRuntimeSpan<Sp, 1>(Sp{sarr}); + testRuntimeSpan<Sp, 2>(Sp{sarr}); + testRuntimeSpan<Sp, 3>(Sp{sarr}); + testRuntimeSpan<Sp, 4>(Sp{sarr}); + testRuntimeSpan<Sp, 5>(Sp{sarr}); + } + + { + using Sp = std::span<std::string, 5>; + + testRuntimeSpan<Sp, 0>(Sp{sarr}); + testRuntimeSpan<Sp, 1>(Sp{sarr}); + testRuntimeSpan<Sp, 2>(Sp{sarr}); + testRuntimeSpan<Sp, 3>(Sp{sarr}); + testRuntimeSpan<Sp, 4>(Sp{sarr}); + testRuntimeSpan<Sp, 5>(Sp{sarr}); + } +} diff --git a/libcxx/test/std/containers/views/span.sub/last.pass.cpp b/libcxx/test/std/containers/views/span.sub/last.pass.cpp new file mode 100644 index 00000000000..4e378fe549e --- /dev/null +++ b/libcxx/test/std/containers/views/span.sub/last.pass.cpp @@ -0,0 +1,136 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<ptrdiff_t Count> +// constexpr span<element_type, Count> last() const; +// +// constexpr span<element_type, dynamic_extent> last(index_type count) const; +// +// Requires: 0 <= Count && Count <= size(). + + +#include <span> +#include <cassert> +#include <algorithm> +#include <string> + +#include "test_macros.h" + +template <typename Span, ptrdiff_t Count> +constexpr bool testConstexprSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template last<Count>()))); + LIBCPP_ASSERT((noexcept(sp.last(Count)))); + auto s1 = sp.template last<Count>(); + auto s2 = sp.last(Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == Count, ""); + static_assert(S2::extent == std::dynamic_extent, ""); + return + s1.data() == s2.data() + && s1.size() == s2.size() + && std::equal(s1.begin(), s1.end(), sp.end() - Count); +} + + +template <typename Span, ptrdiff_t Count> +void testRuntimeSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template last<Count>()))); + LIBCPP_ASSERT((noexcept(sp.last(Count)))); + auto s1 = sp.template last<Count>(); + auto s2 = sp.last(Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == Count, ""); + static_assert(S2::extent == std::dynamic_extent, ""); + assert(s1.data() == s2.data()); + assert(s1.size() == s2.size()); + assert(std::equal(s1.begin(), s1.end(), sp.end() - Count)); +} + + +constexpr int carr1[] = {1,2,3,4}; + int arr[] = {5,6,7}; +std::string sarr [] = { "ABC", "DEF", "GHI", "JKL", "MNO"}; + +int main () +{ + { + using Sp = std::span<const int>; + static_assert(testConstexprSpan<Sp, 0>(Sp{}), ""); + + static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); + } + + { + using Sp = std::span<const int, 4>; + + static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); + } + + { + using Sp = std::span<int>; + testRuntimeSpan<Sp, 0>(Sp{}); + + testRuntimeSpan<Sp, 0>(Sp{arr}); + testRuntimeSpan<Sp, 1>(Sp{arr}); + testRuntimeSpan<Sp, 2>(Sp{arr}); + testRuntimeSpan<Sp, 3>(Sp{arr}); + } + + { + using Sp = std::span<int, 3>; + + testRuntimeSpan<Sp, 0>(Sp{arr}); + testRuntimeSpan<Sp, 1>(Sp{arr}); + testRuntimeSpan<Sp, 2>(Sp{arr}); + testRuntimeSpan<Sp, 3>(Sp{arr}); + } + + { + using Sp = std::span<std::string>; + testConstexprSpan<Sp, 0>(Sp{}); + + testRuntimeSpan<Sp, 0>(Sp{sarr}); + testRuntimeSpan<Sp, 1>(Sp{sarr}); + testRuntimeSpan<Sp, 2>(Sp{sarr}); + testRuntimeSpan<Sp, 3>(Sp{sarr}); + testRuntimeSpan<Sp, 4>(Sp{sarr}); + testRuntimeSpan<Sp, 5>(Sp{sarr}); + } + + { + using Sp = std::span<std::string, 5>; + + testRuntimeSpan<Sp, 0>(Sp{sarr}); + testRuntimeSpan<Sp, 1>(Sp{sarr}); + testRuntimeSpan<Sp, 2>(Sp{sarr}); + testRuntimeSpan<Sp, 3>(Sp{sarr}); + testRuntimeSpan<Sp, 4>(Sp{sarr}); + testRuntimeSpan<Sp, 5>(Sp{sarr}); + } +} diff --git a/libcxx/test/std/containers/views/span.sub/subspan.pass.cpp b/libcxx/test/std/containers/views/span.sub/subspan.pass.cpp new file mode 100644 index 00000000000..79cdc7bcaf1 --- /dev/null +++ b/libcxx/test/std/containers/views/span.sub/subspan.pass.cpp @@ -0,0 +1,210 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<ptrdiff_t Offset, ptrdiff_t Count = dynamic_extent> +// constexpr span<element_type, see below> subspan() const; +// +// constexpr span<element_type, dynamic_extent> subspan( +// index_type offset, index_type count = dynamic_extent) const; +// +// Requires: (0 <= Offset && Offset <= size()) +// && (Count == dynamic_extent || Count >= 0 && Offset + Count <= size()) + +#include <span> +#include <cassert> +#include <algorithm> +#include <string> + +#include "test_macros.h" + +template <typename Span, ptrdiff_t Offset, ptrdiff_t Count> +constexpr bool testConstexprSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>()))); + LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count)))); + auto s1 = sp.template subspan<Offset, Count>(); + auto s2 = sp.subspan(Offset, Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Count), ""); + static_assert(S2::extent == std::dynamic_extent, ""); + return + s1.data() == s2.data() + && s1.size() == s2.size() + && std::equal(s1.begin(), s1.end(), sp.begin() + Offset); +} + +template <typename Span, ptrdiff_t Offset> +constexpr bool testConstexprSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>()))); + LIBCPP_ASSERT((noexcept(sp.subspan(Offset)))); + auto s1 = sp.template subspan<Offset>(); + auto s2 = sp.subspan(Offset); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), ""); + static_assert(S2::extent == std::dynamic_extent, ""); + return + s1.data() == s2.data() + && s1.size() == s2.size() + && std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end()); +} + + +template <typename Span, ptrdiff_t Offset, ptrdiff_t Count> +void testRuntimeSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template subspan<Offset, Count>()))); + LIBCPP_ASSERT((noexcept(sp.subspan(Offset, Count)))); + auto s1 = sp.template subspan<Offset, Count>(); + auto s2 = sp.subspan(Offset, Count); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Count), ""); + static_assert(S2::extent == std::dynamic_extent, ""); + assert(s1.data() == s2.data()); + assert(s1.size() == s2.size()); + assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset)); +} + + +template <typename Span, ptrdiff_t Offset> +void testRuntimeSpan(Span sp) +{ + LIBCPP_ASSERT((noexcept(sp.template subspan<Offset>()))); + LIBCPP_ASSERT((noexcept(sp.subspan(Offset)))); + auto s1 = sp.template subspan<Offset>(); + auto s2 = sp.subspan(Offset); + using S1 = decltype(s1); + using S2 = decltype(s2); + ASSERT_SAME_TYPE(typename Span::value_type, typename S1::value_type); + ASSERT_SAME_TYPE(typename Span::value_type, typename S2::value_type); + static_assert(S1::extent == (Span::extent == std::dynamic_extent ? std::dynamic_extent : Span::extent - Offset), ""); + static_assert(S2::extent == std::dynamic_extent, ""); + assert(s1.data() == s2.data()); + assert(s1.size() == s2.size()); + assert(std::equal(s1.begin(), s1.end(), sp.begin() + Offset, sp.end())); +} + + +constexpr int carr1[] = {1,2,3,4}; + int arr1[] = {5,6,7}; + +int main () +{ + { + using Sp = std::span<const int>; + static_assert(testConstexprSpan<Sp, 0>(Sp{}), ""); + + static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), ""); + + static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), ""); + } + + { + using Sp = std::span<const int, 4>; + + static_assert(testConstexprSpan<Sp, 0, 4>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 0, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 0, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 0, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 0, 0>(Sp{carr1}), ""); + + static_assert(testConstexprSpan<Sp, 1, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 2, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 3, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 4, 0>(Sp{carr1}), ""); + } + + { + using Sp = std::span<const int>; + static_assert(testConstexprSpan<Sp, 0>(Sp{}), ""); + + static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); + } + + { + using Sp = std::span<const int, 4>; + + static_assert(testConstexprSpan<Sp, 0>(Sp{carr1}), ""); + + static_assert(testConstexprSpan<Sp, 1>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 2>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 3>(Sp{carr1}), ""); + static_assert(testConstexprSpan<Sp, 4>(Sp{carr1}), ""); + } + + { + using Sp = std::span<int>; + testRuntimeSpan<Sp, 0>(Sp{}); + + testRuntimeSpan<Sp, 0, 3>(Sp{arr1}); + testRuntimeSpan<Sp, 0, 2>(Sp{arr1}); + testRuntimeSpan<Sp, 0, 1>(Sp{arr1}); + testRuntimeSpan<Sp, 0, 0>(Sp{arr1}); + + testRuntimeSpan<Sp, 1, 2>(Sp{arr1}); + testRuntimeSpan<Sp, 2, 1>(Sp{arr1}); + testRuntimeSpan<Sp, 3, 0>(Sp{arr1}); + } + + { + using Sp = std::span<int, 3>; + + testRuntimeSpan<Sp, 0, 3>(Sp{arr1}); + testRuntimeSpan<Sp, 0, 2>(Sp{arr1}); + testRuntimeSpan<Sp, 0, 1>(Sp{arr1}); + testRuntimeSpan<Sp, 0, 0>(Sp{arr1}); + + testRuntimeSpan<Sp, 1, 2>(Sp{arr1}); + testRuntimeSpan<Sp, 2, 1>(Sp{arr1}); + testRuntimeSpan<Sp, 3, 0>(Sp{arr1}); + } + + { + using Sp = std::span<int>; + testRuntimeSpan<Sp, 0>(Sp{}); + + testRuntimeSpan<Sp, 0>(Sp{arr1}); + testRuntimeSpan<Sp, 1>(Sp{arr1}); + testRuntimeSpan<Sp, 2>(Sp{arr1}); + testRuntimeSpan<Sp, 3>(Sp{arr1}); + } + + { + using Sp = std::span<int, 3>; + + testRuntimeSpan<Sp, 0>(Sp{arr1}); + testRuntimeSpan<Sp, 1>(Sp{arr1}); + testRuntimeSpan<Sp, 2>(Sp{arr1}); + testRuntimeSpan<Sp, 3>(Sp{arr1}); + } +} diff --git a/libcxx/test/std/containers/views/types.pass.cpp b/libcxx/test/std/containers/views/types.pass.cpp new file mode 100644 index 00000000000..082abeb774e --- /dev/null +++ b/libcxx/test/std/containers/views/types.pass.cpp @@ -0,0 +1,107 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template<class ElementType, ptrdiff_t Extent = dynamic_extent> +// class span { +// public: +// // constants and types +// using element_type = ElementType; +// using value_type = remove_cv_t<ElementType>; +// using index_type = ptrdiff_t; +// using difference_type = ptrdiff_t; +// using pointer = element_type *; +// using reference = element_type &; +// using iterator = implementation-defined; +// using const_iterator = implementation-defined; +// using reverse_iterator = std::reverse_iterator<iterator>; +// using const_reverse_iterator = std::reverse_iterator<const_iterator>; +// +// static constexpr index_type extent = Extent; +// + +#include <span> +#include <cassert> +#include <iterator> +#include <string> + +#include "test_macros.h" + +template <typename S, typename Iter> +void testIterator() +{ + typedef std::iterator_traits<Iter> ItT; + + ASSERT_SAME_TYPE(typename ItT::iterator_category, std::random_access_iterator_tag); + ASSERT_SAME_TYPE(typename ItT::value_type, typename S::value_type); + ASSERT_SAME_TYPE(typename ItT::reference, typename S::reference); + ASSERT_SAME_TYPE(typename ItT::pointer, typename S::pointer); + ASSERT_SAME_TYPE(typename ItT::difference_type, typename S::difference_type); +} + +template <typename S, typename Iter> +void testConstIterator() +{ + typedef std::iterator_traits<Iter> ItT; + + ASSERT_SAME_TYPE(typename ItT::iterator_category, std::random_access_iterator_tag); + ASSERT_SAME_TYPE(typename ItT::value_type, typename S::value_type); +// I'd like to say 'const typename S::pointer' here, but that gives me +// a const pointer to a non-const value, which is not what I want. + ASSERT_SAME_TYPE(typename ItT::reference, typename S::element_type const &); + ASSERT_SAME_TYPE(typename ItT::pointer, typename S::element_type const *); + ASSERT_SAME_TYPE(typename ItT::difference_type, typename S::difference_type); +} + +template <typename S, typename ElementType, std::ptrdiff_t Size> +void testSpan() +{ + ASSERT_SAME_TYPE(typename S::element_type, ElementType); + ASSERT_SAME_TYPE(typename S::value_type, std::remove_cv_t<ElementType>); + ASSERT_SAME_TYPE(typename S::index_type, std::ptrdiff_t); + ASSERT_SAME_TYPE(typename S::difference_type, std::ptrdiff_t); + ASSERT_SAME_TYPE(typename S::pointer, ElementType *); + ASSERT_SAME_TYPE(typename S::reference, ElementType &); + + static_assert(S::extent == Size); // check that it exists + + testIterator<S, typename S::iterator>(); + testIterator<S, typename S::reverse_iterator>(); + testConstIterator<S, typename S::const_iterator>(); + testConstIterator<S, typename S::const_reverse_iterator>(); +} + + +template <typename T> +void test() +{ + testSpan<std::span< T>, T, -1>(); + testSpan<std::span<const T>, const T, -1>(); + testSpan<std::span< volatile T>, volatile T, -1>(); + testSpan<std::span<const volatile T>, const volatile T, -1>(); + + testSpan<std::span< T, 5>, T, 5>(); + testSpan<std::span<const T, 5>, const T, 5>(); + testSpan<std::span< volatile T, 5>, volatile T, 5>(); + testSpan<std::span<const volatile T, 5>, const volatile T, 5>(); +} + +struct A{}; + +int main () +{ + test<int>(); + test<long>(); + test<double>(); + test<std::string>(); + test<A>(); +} |

