From e5cb744bf12d4a35a69a756b15d55d0379c47ac0 Mon Sep 17 00:00:00 2001 From: Marshall Clow Date: Mon, 25 Feb 2019 17:54:08 +0000 Subject: [PATCH] First part of P1024: Usability Enhancements for std::span. Remove operator() for indexing, and add 'front' and 'back' calls. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@354801 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/span | 28 +++++-- .../containers/views/span.elem/back.pass.cpp | 75 +++++++++++++++++++ .../containers/views/span.elem/front.pass.cpp | 75 +++++++++++++++++++ .../views/span.elem/op_idx.pass.cpp | 12 +-- 4 files changed, 175 insertions(+), 15 deletions(-) create mode 100644 test/std/containers/views/span.elem/back.pass.cpp create mode 100644 test/std/containers/views/span.elem/front.pass.cpp diff --git a/include/span b/include/span index 774f69823..b212f8722 100644 --- a/include/span +++ b/include/span @@ -88,7 +88,8 @@ public: // [span.elem], span element access constexpr reference operator[](index_type idx) const; - constexpr reference operator()(index_type idx) const; + constexpr reference front() const; + constexpr reference back() const; constexpr pointer data() const noexcept; // [span.iterators], span iterator support @@ -319,10 +320,16 @@ public: return __data[__idx]; } - _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept + _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept { - _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span() index out of bounds"); - return __data[__idx]; + static_assert(_Extent > 0, "span[].front() on empty span"); + return __data[0]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept + { + static_assert(_Extent > 0, "span[].back() on empty span"); + return __data[size()-1]; } _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } @@ -484,12 +491,19 @@ public: return __data[__idx]; } - _LIBCPP_INLINE_VISIBILITY constexpr reference operator()(index_type __idx) const noexcept + _LIBCPP_INLINE_VISIBILITY constexpr reference front() const noexcept { - _LIBCPP_ASSERT(__idx >= 0 && __idx < size(), "span() index out of bounds"); - return __data[__idx]; + _LIBCPP_ASSERT(!empty(), "span[].front() on empty span"); + return __data[0]; } + _LIBCPP_INLINE_VISIBILITY constexpr reference back() const noexcept + { + _LIBCPP_ASSERT(!empty(), "span[].back() on empty span"); + return __data[size()-1]; + } + + _LIBCPP_INLINE_VISIBILITY constexpr pointer data() const noexcept { return __data; } // [span.iter], span iterator support diff --git a/test/std/containers/views/span.elem/back.pass.cpp b/test/std/containers/views/span.elem/back.pass.cpp new file mode 100644 index 000000000..775aed6cb --- /dev/null +++ b/test/std/containers/views/span.elem/back.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 + +// + +// constexpr reference back() const noexcept; +// Expects: empty() is false. +// Effects: Equivalent to: return *(data() + (size() - 1)); +// + + +#include +#include +#include + +#include "test_macros.h" + + +template +constexpr bool testConstexprSpan(Span sp) +{ + _LIBCPP_ASSERT(sp.back(), ""); + return std::addressof(sp.back()) == sp.data() + sp.size() - 1; +} + + +template +void testRuntimeSpan(Span sp) +{ + _LIBCPP_ASSERT(sp.back(), ""); + assert(std::addressof(sp.back()) == sp.data() + sp.size() - 1); +} + + +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_assert(testConstexprSpan(std::span(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4)), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4)), ""); + + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + + std::string s; + testRuntimeSpan(std::span (&s, 1)); + testRuntimeSpan(std::span(&s, 1)); + + return 0; +} diff --git a/test/std/containers/views/span.elem/front.pass.cpp b/test/std/containers/views/span.elem/front.pass.cpp new file mode 100644 index 000000000..ca381b289 --- /dev/null +++ b/test/std/containers/views/span.elem/front.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 + +// + +// constexpr reference front() const noexcept; +// Expects: empty() is false. +// Effects: Equivalent to: return *data(); +// + + +#include +#include +#include + +#include "test_macros.h" + + +template +constexpr bool testConstexprSpan(Span sp) +{ + _LIBCPP_ASSERT(sp.front(), ""); + return std::addressof(sp.front()) == sp.data(); +} + + +template +void testRuntimeSpan(Span sp) +{ + _LIBCPP_ASSERT(sp.front(), ""); + assert(std::addressof(sp.front()) == sp.data()); +} + + +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_assert(testConstexprSpan(std::span(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4)), ""); + + static_assert(testConstexprSpan(std::span(iArr1, 1)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 2)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 3)), ""); + static_assert(testConstexprSpan(std::span(iArr1, 4)), ""); + + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + + + testRuntimeSpan(std::span(iArr2, 1)); + testRuntimeSpan(std::span(iArr2, 2)); + testRuntimeSpan(std::span(iArr2, 3)); + testRuntimeSpan(std::span(iArr2, 4)); + + std::string s; + testRuntimeSpan(std::span (&s, 1)); + testRuntimeSpan(std::span(&s, 1)); + + return 0; +} diff --git a/test/std/containers/views/span.elem/op_idx.pass.cpp b/test/std/containers/views/span.elem/op_idx.pass.cpp index c56be7d3e..cb63ec9d1 100644 --- a/test/std/containers/views/span.elem/op_idx.pass.cpp +++ b/test/std/containers/views/span.elem/op_idx.pass.cpp @@ -26,12 +26,10 @@ template 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; + typename Span::reference r2 = *(sp.data() + idx); + return r1 == r2; } @@ -39,12 +37,10 @@ template 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); + typename Span::reference r2 = *(sp.data() + idx); + assert(r1 == r2); } struct A{};