Implment the last part of P1024: tuple-like interface to span. Reviewed as https://reviews.llvm.org/D58706. llvm-svn: 354988 GitOrigin-RevId: 02e1651c1f25a960391a6bd8fcd4989539fe5183
diff --git a/include/span b/include/span index 606f9a9..35461bf 100644 --- a/include/span +++ b/include/span
@@ -522,20 +522,52 @@ index_type __size; }; +// tuple interface +template <class _Tp, size_t _Size> +struct _LIBCPP_TEMPLATE_VIS tuple_size<span<_Tp, _Size>> + : public integral_constant<size_t, _Size> {}; + +template <class _Tp> +struct _LIBCPP_TEMPLATE_VIS tuple_size<span<_Tp, dynamic_extent>>; // declared but not defined + + +template <size_t _Ip, class _Tp, size_t _Size> +class _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, span<_Tp, _Size>> +{ + static_assert( dynamic_extent != _Size, "std::tuple_element<> not supported for std::span<T, dynamic_extent>"); + static_assert(_Ip < _Size, "Index out of bounds in std::tuple_element<> (std::span)"); +public: + typedef _Tp type; +}; + +template <size_t _Ip, class _Tp, size_t _Size> +_LIBCPP_INLINE_VISIBILITY constexpr +_Tp& +get(span<_Tp, _Size> __s) noexcept +{ + static_assert( dynamic_extent != _Size, "std::get<> not supported for std::span<T, dynamic_extent>"); + static_assert(_Ip < _Size, "Index out of bounds in std::get<> (std::span)"); + return __s[_Ip]; +} + + // as_bytes & as_writeable_bytes template <class _Tp, size_t _Extent> - auto as_bytes(span<_Tp, _Extent> __s) noexcept - -> decltype(__s.__as_bytes()) - { return __s.__as_bytes(); } +_LIBCPP_INLINE_VISIBILITY +auto as_bytes(span<_Tp, _Extent> __s) noexcept +-> decltype(__s.__as_bytes()) +{ return __s.__as_bytes(); } template <class _Tp, size_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(); } +_LIBCPP_INLINE_VISIBILITY +auto as_writeable_bytes(span<_Tp, _Extent> __s) noexcept +-> typename enable_if_t<!is_const_v<_Tp>, decltype(__s.__as_writeable_bytes())> +{ return __s.__as_writeable_bytes(); } template <class _Tp, size_t _Extent> - constexpr void swap(span<_Tp, _Extent> &__lhs, span<_Tp, _Extent> &__rhs) noexcept - { __lhs.swap(__rhs); } +_LIBCPP_INLINE_VISIBILITY +constexpr void swap(span<_Tp, _Extent> &__lhs, span<_Tp, _Extent> &__rhs) noexcept +{ __lhs.swap(__rhs); } // Deduction guides
diff --git a/test/std/containers/views/span.tuple/get.fail.cpp b/test/std/containers/views/span.tuple/get.fail.cpp new file mode 100644 index 0000000..7544ea3 --- /dev/null +++ b/test/std/containers/views/span.tuple/get.fail.cpp
@@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template <size_t _Ip, ElementType, size_t Extent> +// constexpr ElementType& get(span<ElementType, Extent> s) noexcept; + +#include <span> + +#include "test_macros.h" + + +int main(int, char**) +{ +// No get for dynamic spans + constexpr int arr [] = {0,1,2,3,4,5,6,7,8,9}; + (void) std::get< 0>(std::span<const int, 0>(arr, (size_t)0)); // expected-error-re@span:* {{static_assert failed{{( due to requirement '.*')?}} "Index out of bounds in std::get<> (std::span)"}} + (void) std::get< 5>(std::span<const int, 5>(arr, 5)); // expected-error-re@span:* {{static_assert failed{{( due to requirement '.*')?}} "Index out of bounds in std::get<> (std::span)"}} + (void) std::get<20>(std::span<const int, 10>(arr, 10)); // expected-error-re@span:* {{static_assert failed{{( due to requirement '.*')?}} "Index out of bounds in std::get<> (std::span)"}} + + return 0; +}
diff --git a/test/std/containers/views/span.tuple/get.pass.cpp b/test/std/containers/views/span.tuple/get.pass.cpp new file mode 100644 index 0000000..4c8c85e --- /dev/null +++ b/test/std/containers/views/span.tuple/get.pass.cpp
@@ -0,0 +1,75 @@ +// -*- C++ -*- +//===------------------------------ span ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// template <size_t _Ip, ElementType, size_t Extent> +// constexpr ElementType& get(span<ElementType, Extent> s) noexcept; +// + + +#include <span> +#include <cassert> +#include <string> + +#include "test_macros.h" + + +template <size_t Idx, typename Span> +constexpr bool testConstexprSpan(Span sp, typename Span::pointer ptr) +{ + ASSERT_NOEXCEPT(std::get<Idx>(sp)); + return std::addressof(std::get<Idx>(sp)) == ptr; +} + + +template <size_t Idx, typename Span> +void testRuntimeSpan(Span sp, typename Span::pointer ptr) +{ + ASSERT_NOEXCEPT(std::get<Idx>(sp)); + assert(std::addressof(std::get<Idx>(sp)) == 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(int, char**) +{ + +// static size + static_assert(testConstexprSpan<0>(std::span<const int, 4>(iArr1, 1), iArr1 + 0), ""); + static_assert(testConstexprSpan<1>(std::span<const int, 4>(iArr1, 2), iArr1 + 1), ""); + static_assert(testConstexprSpan<2>(std::span<const int, 4>(iArr1, 3), iArr1 + 2), ""); + static_assert(testConstexprSpan<3>(std::span<const int, 4>(iArr1, 4), iArr1 + 3), ""); + + static_assert(testConstexprSpan<0>(std::span<const int, 1>(iArr1 + 1, 1), iArr1 + 1), ""); + static_assert(testConstexprSpan<1>(std::span<const int, 2>(iArr1 + 2, 2), iArr1 + 3), ""); + static_assert(testConstexprSpan<2>(std::span<const int, 3>(iArr1 + 3, 3), iArr1 + 5), ""); + static_assert(testConstexprSpan<3>(std::span<const int, 4>(iArr1 + 4, 4), iArr1 + 7), ""); + +// static size + testRuntimeSpan<0>(std::span<int, 4>(iArr2, 4), iArr2); + testRuntimeSpan<1>(std::span<int, 4>(iArr2, 1), iArr2 + 1); + testRuntimeSpan<2>(std::span<int, 4>(iArr2, 2), iArr2 + 2); + testRuntimeSpan<3>(std::span<int, 4>(iArr2, 3), iArr2 + 3); + + testRuntimeSpan<0>(std::span<int, 4>(iArr2 + 1, 1), iArr2 + 1); + testRuntimeSpan<1>(std::span<int, 4>(iArr2 + 2, 2), iArr2 + 3); + testRuntimeSpan<2>(std::span<int, 4>(iArr2 + 3, 3), iArr2 + 5); + testRuntimeSpan<3>(std::span<int, 4>(iArr2 + 4, 4), iArr2 + 7); + + + std::string s; + testRuntimeSpan<0>(std::span<std::string, 1>(&s, 1), &s); + + + return 0; +}
diff --git a/test/std/containers/views/span.tuple/tuple_element.fail.cpp b/test/std/containers/views/span.tuple/tuple_element.fail.cpp new file mode 100644 index 0000000..4ecec6b --- /dev/null +++ b/test/std/containers/views/span.tuple/tuple_element.fail.cpp
@@ -0,0 +1,27 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// tuple_element<I, span<T, N> >::type + +#include <span> + +#include "test_macros.h" + + +int main(int, char**) +{ +// No tuple_element for dynamic spans + using T1 = typename std::tuple_element< 0, std::span<int, 0>>::type; // expected-error-re@span:* {{static_assert failed{{( due to requirement '.*')?}} "Index out of bounds in std::tuple_element<> (std::span)"}} + using T2 = typename std::tuple_element< 5, std::span<int, 5>>::type; // expected-error-re@span:* {{static_assert failed{{( due to requirement '.*')?}} "Index out of bounds in std::tuple_element<> (std::span)"}} + using T3 = typename std::tuple_element<20, std::span<int, 10>>::type; // expected-error-re@span:* {{static_assert failed{{( due to requirement '.*')?}} "Index out of bounds in std::tuple_element<> (std::span)"}} + + return 0; +}
diff --git a/test/std/containers/views/span.tuple/tuple_element.pass.cpp b/test/std/containers/views/span.tuple/tuple_element.pass.cpp new file mode 100644 index 0000000..777cb85 --- /dev/null +++ b/test/std/containers/views/span.tuple/tuple_element.pass.cpp
@@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// tuple_element<I, span<T, N> >::type + +#include <span> + +#include "test_macros.h" + +template <class T, std::size_t N, std::size_t Idx> +void test() +{ + { + typedef std::span<T, N> C; + ASSERT_SAME_TYPE(typename std::tuple_element<Idx, C>::type, T); + } + { + typedef std::span<T const, N> C; + ASSERT_SAME_TYPE(typename std::tuple_element<Idx, C>::type, T const); + } + { + typedef std::span<T volatile, N> C; + ASSERT_SAME_TYPE(typename std::tuple_element<Idx, C>::type, T volatile); + } + { + typedef std::span<T const volatile, N> C; + ASSERT_SAME_TYPE(typename std::tuple_element<Idx, C>::type, T const volatile); + } +} + +int main(int, char**) +{ + test<double, 3, 0>(); + test<double, 3, 1>(); + test<double, 3, 2>(); + + test<int, 5, 0>(); + test<int, 5, 1>(); + test<int, 5, 2>(); + test<int, 5, 3>(); + test<int, 5, 4>(); + + return 0; +}
diff --git a/test/std/containers/views/span.tuple/tuple_size.fail.cpp b/test/std/containers/views/span.tuple/tuple_size.fail.cpp new file mode 100644 index 0000000..1d3d5b3 --- /dev/null +++ b/test/std/containers/views/span.tuple/tuple_size.fail.cpp
@@ -0,0 +1,21 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// tuple_size<span<T, N> >::value + +#include <span> + +int main(int, char**) +{ + (void) std::tuple_size<std::span<double>>::value; // expected-error-re {{implicit instantiation of undefined template 'std::__1::tuple_size<std::__1::span<double, {{.*}}}} + (void) std::tuple_size<std::span<int>>::value; // expected-error-re {{implicit instantiation of undefined template 'std::__1::tuple_size<std::__1::span<int, {{.*}}}} + return 0; +}
diff --git a/test/std/containers/views/span.tuple/tuple_size.pass.cpp b/test/std/containers/views/span.tuple/tuple_size.pass.cpp new file mode 100644 index 0000000..a239402 --- /dev/null +++ b/test/std/containers/views/span.tuple/tuple_size.pass.cpp
@@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// <span> + +// tuple_size<span<T, N> >::value + +#include <span> + +template <class T, std::size_t N> +void test() +{ + { + typedef std::span<T, N> C; + static_assert((std::tuple_size<C>::value == N), ""); + } + { + typedef std::span<T const, N> C; + static_assert((std::tuple_size<C>::value == N), ""); + } + { + typedef std::span<T volatile, N> C; + static_assert((std::tuple_size<C>::value == N), ""); + } + { + typedef std::span<T const volatile, N> C; + static_assert((std::tuple_size<C>::value == N), ""); + } +} + +int main(int, char**) +{ + test<double, 0>(); + test<double, 3>(); + test<double, 5>(); + + return 0; +}
diff --git a/www/cxx2a_status.html b/www/cxx2a_status.html index e062287..fc47072 100644 --- a/www/cxx2a_status.html +++ b/www/cxx2a_status.html
@@ -144,9 +144,9 @@ <tr><td><a href="https://wg21.link/P0811R3">P0811R3</a></td><td>LWG</td><td>Well-behaved interpolation for numbers and pointers</td><td>Kona</td><td></td><td></td></tr> <tr><td><a href="https://wg21.link/P0920R2">P0920R2</a></td><td>LWG</td><td>Precalculated hash values in lookup</td><td>Kona</td><td></td><td></td></tr> <tr><td><a href="https://wg21.link/P1001R2">P1001R2</a></td><td>LWG</td><td>Target Vectorization Policies from Parallelism V2 TS to C++20</td><td>Kona</td><td></td><td></td></tr> - <tr><td><a href="https://wg21.link/P1024R3">P1024R3</a></td><td>LWG</td><td>Usability Enhancements for std::span</td><td>Kona</td><td></td><td></td></tr> + <tr><td><a href="https://wg21.link/P1024R3">P1024R3</a></td><td>LWG</td><td>Usability Enhancements for std::span</td><td>Kona</td><td>Complete</td><td>9.0</td></tr> <tr><td><a href="https://wg21.link/P1164R1">P1164R1</a></td><td>LWG</td><td>Make create_directory() Intuitive</td><td>Kona</td><td></td><td></td></tr> - <tr><td><a href="https://wg21.link/P1227R2">P1227R2</a></td><td>LWG</td><td>Signed ssize() functions, unsigned size() functions </td><td>Kona</td><td></td><td></td></tr> + <tr><td><a href="https://wg21.link/P1227R2">P1227R2</a></td><td>LWG</td><td>Signed ssize() functions, unsigned size() functions </td><td>Kona</td><td>Complete</td><td>9.0</td></tr> <tr><td><a href="https://wg21.link/P1252R2">P1252R2</a></td><td>LWG</td><td>Ranges Design Cleanup</td><td>Kona</td><td></td><td></td></tr> <tr><td><a href="https://wg21.link/P1286R2">P1286R2</a></td><td>CWG</td><td>Contra CWG DR1778</td><td>Kona</td><td></td><td></td></tr> <tr><td><a href="https://wg21.link/P1357R1">P1357R1</a></td><td>LWG</td><td>Traits for [Un]bounded Arrays</td><td>Kona</td><td>Complete</td><td>9.0</td></tr> @@ -323,7 +323,7 @@ <!-- <tr><td></td><td></td><td></td><td></td></tr> --> </table> - <p>Last Updated: 26-Feb-2018</p> + <p>Last Updated: 27-Feb-2018</p> </div> </body> </html>