From def223a596db6178c6e0f0fde68b4c4c932c91f9 Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Mon, 3 Jul 2023 16:52:16 +0200 Subject: [PATCH] Implement `ranges::elements_view` --- .../range.elements/adaptor.pass.cpp | 217 +++++++ .../range.elements/base.pass.cpp | 99 ++++ .../range.elements/begin.pass.cpp | 127 ++++ .../range.elements/borrowed.compile.pass.cpp | 37 ++ .../range.elements/ctor.default.pass.cpp | 47 ++ .../range.elements/ctor.view.pass.cpp | 45 ++ .../range.elements/end.pass.cpp | 162 ++++++ .../iterator/arithmetic.pass.cpp | 151 +++++ .../range.elements/iterator/base.pass.cpp | 110 ++++ .../range.elements/iterator/compare.pass.cpp | 167 ++++++ .../iterator/ctor.base.pass.cpp | 55 ++ .../iterator/ctor.default.pass.cpp | 59 ++ .../iterator/ctor.other.pass.cpp | 73 +++ .../iterator/decrement.pass.cpp | 107 ++++ .../range.elements/iterator/deref.pass.cpp | 102 ++++ .../iterator/increment.pass.cpp | 79 +++ .../iterator/member_types.compile.pass.cpp | 107 ++++ .../iterator/subscript.pass.cpp | 81 +++ .../range.concept.compile.pass.cpp | 92 +++ .../range.elements/sentinel/base.pass.cpp | 50 ++ .../sentinel/ctor.base.pass.cpp | 60 ++ .../sentinel/ctor.convert.pass.cpp | 105 ++++ .../sentinel/ctor.default.pass.cpp | 57 ++ .../range.elements/sentinel/equality.pass.cpp | 214 +++++++ .../range.elements/sentinel/minus.pass.cpp | 241 ++++++++ .../range.elements/size.pass.cpp | 109 ++++ .../range.adaptors/range.elements/types.h | 121 ++++ .../std/detail/libcxx/include/CMakeLists.txt | 1 + .../libcxx/include/__ranges/elements_view.h | 547 ++++++++++++++++++ .../cuda/std/detail/libcxx/include/ranges | 22 + .../range.elements/adaptor.pass.cpp | 184 ++++++ .../range.elements/base.pass.cpp | 84 +++ .../range.elements/begin.pass.cpp | 88 +++ .../range.elements/borrowed.compile.pass.cpp | 36 ++ .../range.elements/ctor.default.pass.cpp | 47 ++ .../range.elements/ctor.view.pass.cpp | 44 ++ .../range.elements/end.pass.cpp | 142 +++++ .../range.elements/general.pass.cpp | 104 ++++ .../iterator/arithmetic.pass.cpp | 123 ++++ .../range.elements/iterator/base.pass.cpp | 98 ++++ .../range.elements/iterator/compare.pass.cpp | 155 +++++ .../iterator/ctor.base.pass.cpp | 54 ++ .../iterator/ctor.default.pass.cpp | 58 ++ .../iterator/ctor.other.pass.cpp | 73 +++ .../iterator/decrement.pass.cpp | 91 +++ .../range.elements/iterator/deref.pass.cpp | 100 ++++ .../iterator/increment.pass.cpp | 78 +++ .../iterator/member_types.compile.pass.cpp | 93 +++ .../iterator/subscript.pass.cpp | 69 +++ .../range.concept.compile.pass.cpp | 79 +++ .../range.elements/sentinel/base.pass.cpp | 41 ++ .../sentinel/ctor.base.pass.cpp | 52 ++ .../sentinel/ctor.convert.pass.cpp | 88 +++ .../sentinel/ctor.default.pass.cpp | 49 ++ .../range.elements/sentinel/equality.pass.cpp | 164 ++++++ .../range.elements/sentinel/minus.pass.cpp | 214 +++++++ .../range.elements/size.pass.cpp | 88 +++ .../range.adaptors/range.elements/types.h | 118 ++++ 58 files changed, 6058 insertions(+) create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/adaptor.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/base.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/begin.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/borrowed.compile.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/ctor.default.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/ctor.view.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/end.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/arithmetic.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.default.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/decrement.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/deref.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/increment.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/member_types.compile.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/subscript.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.default.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/minus.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/size.pass.cpp create mode 100644 libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/types.h create mode 100644 libcudacxx/include/cuda/std/detail/libcxx/include/__ranges/elements_view.h create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/adaptor.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/base.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/begin.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/borrowed.compile.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/ctor.default.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/ctor.view.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/end.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/general.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/arithmetic.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.default.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/decrement.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/deref.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/increment.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/member_types.compile.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/subscript.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.default.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/sentinel/minus.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/size.pass.cpp create mode 100644 libcudacxx/libcxx/test/std/ranges/range.adaptors/range.elements/types.h diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/adaptor.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/adaptor.pass.cpp new file mode 100644 index 00000000000..8ec2f8f5404 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/adaptor.pass.cpp @@ -0,0 +1,217 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// cuda::std::views::elements +// cuda::std::views::keys +// cuda::std::views::values + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +template +struct View : cuda::std::ranges::view_base { + __host__ __device__ T* begin() const; + __host__ __device__ T* end() const; +}; + +static_assert(!cuda::std::is_invocable_v))>); +static_assert(!cuda::std::is_invocable_v)), View>); +static_assert(cuda::std::is_invocable_v)), View>>); +static_assert(cuda::std::is_invocable_v)), View>>); +static_assert(!cuda::std::is_invocable_v)), View>>); + +static_assert(!cuda::std::is_invocable_v); +static_assert(!cuda::std::is_invocable_v>); +static_assert(cuda::std::is_invocable_v>>); +static_assert(cuda::std::is_invocable_v>>); + +static_assert(!cuda::std::is_invocable_v); +static_assert(!cuda::std::is_invocable_v>); +static_assert(cuda::std::is_invocable_v>>); +static_assert(!cuda::std::is_invocable_v>>); + +#if TEST_STD_VER > 17 +template +concept CanBePiped = requires (View&& view, T&& t) { + { cuda::std::forward(view) | cuda::std::forward(t) }; +}; +#else +template +inline constexpr bool CanBePiped = false; + +template +inline constexpr bool CanBePiped() | cuda::std::declval())>> = true; +#endif + +static_assert(!CanBePiped, decltype((cuda::std::views::elements<0>))>); +static_assert(CanBePiped>, decltype((cuda::std::views::elements<0>))>); +static_assert(CanBePiped>, decltype((cuda::std::views::elements<0>))>); +static_assert(!CanBePiped>, decltype((cuda::std::views::elements<5>))>); + +static_assert(!CanBePiped, decltype((cuda::std::views::keys))>); +static_assert(CanBePiped>, decltype((cuda::std::views::keys))>); +static_assert(CanBePiped>, decltype((cuda::std::views::keys))>); + +static_assert(!CanBePiped, decltype((cuda::std::views::values))>); +static_assert(CanBePiped>, decltype((cuda::std::views::values))>); +static_assert(!CanBePiped>, decltype((cuda::std::views::values))>); + +template +__host__ __device__ constexpr bool equal(Range&& range, Expected&& expected) { + auto irange = range.begin(); + auto iexpected = cuda::std::begin(expected); + for (; irange != range.end(); ++irange, ++iexpected) { + if (*irange != *iexpected) { + return false; + } + } + return true; +} + +__host__ __device__ constexpr bool test() { + cuda::std::pair buff[] = {{1, 2}, {3, 4}, {5, 6}}; + + // Test `views::elements(v)` + { + using Result = cuda::std::ranges::elements_view[3]>, 0>; + decltype(auto) result = cuda::std::views::elements<0>(buff); + static_assert(cuda::std::same_as); + auto expected = {1, 3, 5}; + assert(equal(result, expected)); + } + + // Test `views::keys(v)` + { + using Result = cuda::std::ranges::elements_view[3]>, 0>; + decltype(auto) result = cuda::std::views::keys(buff); + static_assert(cuda::std::same_as); + auto expected = {1, 3, 5}; + assert(equal(result, expected)); + } + + // Test `views::values(v)` + { + using Result = cuda::std::ranges::elements_view[3]>, 1>; + decltype(auto) result = cuda::std::views::values(buff); + static_assert(cuda::std::same_as); + auto expected = {2, 4, 6}; + assert(equal(result, expected)); + } + + // Test `v | views::elements` + { + using Result = cuda::std::ranges::elements_view[3]>, 1>; + decltype(auto) result = buff | cuda::std::views::elements<1>; + static_assert(cuda::std::same_as); + auto expected = {2, 4, 6}; + assert(equal(result, expected)); + } + + // Test `v | views::keys` + { + using Result = cuda::std::ranges::elements_view[3]>, 0>; + decltype(auto) result = buff | cuda::std::views::keys; + static_assert(cuda::std::same_as); + auto expected = {1, 3, 5}; + assert(equal(result, expected)); + } + + // Test `v | views::values` + { + using Result = cuda::std::ranges::elements_view[3]>, 1>; + decltype(auto) result = buff | cuda::std::views::values; + static_assert(cuda::std::same_as); + auto expected = {2, 4, 6}; + assert(equal(result, expected)); + } + + // Test views::elements<0> | views::elements<0> + { + cuda::std::pair, cuda::std::tuple> nested[] = {{{1}, {2}}, {{3}, {4}}, {{5}, {6}}}; + using Result = cuda::std::ranges::elements_view< + cuda::std::ranges::elements_view, cuda::std::tuple>[3]>, 0>, + 0>; + auto const partial = cuda::std::views::elements<0> | cuda::std::views::elements<0>; + decltype(auto) result = nested | partial; + static_assert(cuda::std::same_as); + auto expected = {1, 3, 5}; + assert(equal(result, expected)); + } + + // Test views::keys | views::keys + { + cuda::std::pair, cuda::std::tuple> nested[] = {{{1}, {2}}, {{3}, {4}}, {{5}, {6}}}; + using Result = cuda::std::ranges::elements_view< + cuda::std::ranges::elements_view, cuda::std::tuple>[3]>, 0>, + 0>; + auto const partial = cuda::std::views::keys | cuda::std::views::keys; + decltype(auto) result = nested | partial; + static_assert(cuda::std::same_as); + auto expected = {1, 3, 5}; + assert(equal(result, expected)); + } + + // Test views::values | views::values + { + cuda::std::pair, cuda::std::tuple> nested[] = {{{1}, {2, 3}}, {{4}, {5, 6}}, {{7}, {8, 9}}}; + using Result = cuda::std::ranges::elements_view< + cuda::std::ranges::elements_view, cuda::std::tuple>[3]>, 1>, + 1>; + auto const partial = cuda::std::views::values | cuda::std::views::values; + decltype(auto) result = nested | partial; + static_assert(cuda::std::same_as); + auto expected = {3, 6, 9}; + assert(equal(result, expected)); + } + + // Test views::keys | views::values + { + cuda::std::pair, cuda::std::tuple> nested[] = {{{1, 2}, {3}}, {{4, 5}, {6}}, {{7, 8}, {9}}}; + using Result = cuda::std::ranges::elements_view< + cuda::std::ranges::elements_view, cuda::std::tuple>[3]>, 0>, + 1>; + auto const partial = cuda::std::views::keys | cuda::std::views::values; + decltype(auto) result = nested | partial; + static_assert(cuda::std::same_as); + auto expected = {2, 5, 8}; + assert(equal(result, expected)); + } + + // Test views::values | views::keys + { + cuda::std::pair, cuda::std::tuple> nested[] = {{{1}, {2, 3}}, {{4}, {5, 6}}, {{7}, {8, 9}}}; + using Result = cuda::std::ranges::elements_view< + cuda::std::ranges::elements_view, cuda::std::tuple>[3]>, 1>, + 0>; + auto const partial = cuda::std::views::values | cuda::std::views::keys; + decltype(auto) result = nested | partial; + static_assert(cuda::std::same_as); + auto expected = {2, 5, 8}; + assert(equal(result, expected)); + } + + return true; +} + +int main(int, char**) { + test(); +#if defined(_LIBCUDACXX_ADDRESSOF) \ + && !defined(TEST_COMPILER_NVCC_BELOW_11_3) + static_assert(test()); +#endif // defined(_LIBCUDACXX_ADDRESSOF) && !defined(TEST_COMPILER_NVCC_BELOW_11_3) + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/base.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/base.pass.cpp new file mode 100644 index 00000000000..25e4d4bfa20 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/base.pass.cpp @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr V base() const & requires copy_constructible { return base_; } +// constexpr V base() && { return cuda::std::move(base_); } + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "MoveOnly.h" + +struct View : cuda::std::ranges::view_base { + int i; + __host__ __device__ cuda::std::tuple* begin() const; + __host__ __device__ cuda::std::tuple* end() const; +}; + +struct MoveOnlyView : View { + MoveOnly mo; +}; + +#if TEST_STD_VER > 17 +template +concept HasBase = requires(T&& t) { cuda::std::forward(t).base(); }; +#else +template +inline constexpr bool HasBase = false; + +template +inline constexpr bool HasBase().base())>> = true; +#endif + +static_assert(HasBase const&>); +static_assert(HasBase&&>); + +static_assert(!HasBase const&>); +static_assert(HasBase&&>); + +__host__ __device__ constexpr bool test() { + // const & + { + const cuda::std::ranges::elements_view ev{View{{}, 5}}; + decltype(auto) v = ev.base(); + static_assert(cuda::std::same_as); + assert(v.i == 5); + } + + // & + { + cuda::std::ranges::elements_view ev{View{{}, 5}}; + decltype(auto) v = ev.base(); + static_assert(cuda::std::same_as); + assert(v.i == 5); + } + + // && + { + cuda::std::ranges::elements_view ev{View{{}, 5}}; + decltype(auto) v = cuda::std::move(ev).base(); + static_assert(cuda::std::same_as); + assert(v.i == 5); + } + + // const && + { + const cuda::std::ranges::elements_view ev{View{{}, 5}}; + decltype(auto) v = cuda::std::move(ev).base(); + static_assert(cuda::std::same_as); + assert(v.i == 5); + } + + // move only + { + cuda::std::ranges::elements_view ev{MoveOnlyView{{}, 5}}; + decltype(auto) v = cuda::std::move(ev).base(); + static_assert(cuda::std::same_as); + assert(v.mo.get() == 5); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/begin.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/begin.pass.cpp new file mode 100644 index 00000000000..a707bb2b34e --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/begin.pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr auto begin() requires (!simple-view) +// constexpr auto begin() const requires range + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "types.h" + +#if TEST_STD_VER > 17 +template +concept HasConstBegin = requires(const T ct) { ct.begin(); }; + +template +concept HasBegin = requires(T t) { t.begin(); }; + +template +concept HasConstAndNonConstBegin = + HasConstBegin && + // because const begin and non-const begin returns different types (iterator, iterator) + requires(T t, const T ct) { requires !cuda::std::same_as; }; + +template +concept HasOnlyNonConstBegin = HasBegin && !HasConstBegin; + +template +concept HasOnlyConstBegin = HasConstBegin && !HasConstAndNonConstBegin; +#else +template +inline constexpr bool HasConstBegin = false; + +template +inline constexpr bool HasConstBegin().begin())>> = true; + +template +inline constexpr bool HasBegin = false; + +template +inline constexpr bool HasBegin().begin())>> = true; + +template +inline constexpr bool HasConstAndNonConstBegin = false; + +template +inline constexpr bool HasConstAndNonConstBegin().begin()), + decltype(cuda::std::declval().begin())>>>> = true; + +template +inline constexpr bool HasOnlyNonConstBegin = HasBegin && !HasConstBegin; + +template +inline constexpr bool HasOnlyConstBegin = HasConstBegin && !HasConstAndNonConstBegin; +#endif + +struct NoConstBeginView : TupleBufferView { +#if defined(TEST_COMPILER_NVRTC) // nvbug 3961621 + template + __host__ __device__ constexpr NoConstBeginView(T&& input) : TupleBufferView(cuda::std::forward(input)) {} +#else + using TupleBufferView::TupleBufferView; +#endif + __host__ __device__ constexpr cuda::std::tuple* begin() { return buffer_; } + __host__ __device__ constexpr cuda::std::tuple* end() { return buffer_ + size_; } +}; + +// simple-view +static_assert(HasOnlyConstBegin>); + +// !simple-view && range +static_assert(HasConstAndNonConstBegin>); + +// !range +static_assert(HasOnlyNonConstBegin>); + +__host__ __device__ constexpr bool test() { + cuda::std::tuple buffer[] = {{1}, {2}}; + { + // underlying iterator should be pointing to the first element + auto ev = cuda::std::views::elements<0>(buffer); + auto iter = ev.begin(); + assert(&(*iter) == &cuda::std::get<0>(buffer[0])); + } + + { + // underlying range models simple-view + auto v = cuda::std::views::elements<0>(SimpleCommon{buffer}); + static_assert(cuda::std::is_same_v); + assert(v.begin() == cuda::std::as_const(v).begin()); + auto&& r = *cuda::std::as_const(v).begin(); + assert(&r == &cuda::std::get<0>(buffer[0])); + } + + { + // underlying const R is not a range + auto v = cuda::std::views::elements<0>(NoConstBeginView{buffer}); + auto&& r = *v.begin(); + assert(&r == &cuda::std::get<0>(buffer[0])); + } + + return true; +} + +int main(int, char**) { + test(); +#if defined(_LIBCUDACXX_ADDRESSOF) + static_assert(test()); +#endif // defined(_LIBCUDACXX_ADDRESSOF) + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/borrowed.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/borrowed.compile.pass.cpp new file mode 100644 index 00000000000..b254bc56ea7 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/borrowed.compile.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 +// +// template +// inline constexpr bool enable_borrowed_range> = +// enable_borrowed_range; + +#include +#include + +struct NonBorrowed : cuda::std::ranges::view_base { + __host__ __device__ cuda::std::tuple* begin() { return nullptr; } + __host__ __device__ cuda::std::tuple* end() { return nullptr; } +}; + +struct Borrowed : cuda::std::ranges::view_base { + __host__ __device__ cuda::std::tuple* begin() { return nullptr; } + __host__ __device__ cuda::std::tuple* end() { return nullptr; } +}; + +template <> +inline constexpr bool cuda::std::ranges::enable_borrowed_range = true; + +static_assert(!cuda::std::ranges::borrowed_range>); +static_assert(cuda::std::ranges::borrowed_range>); + +int main(int, char**) { + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/ctor.default.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/ctor.default.pass.cpp new file mode 100644 index 00000000000..9455d593c92 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/ctor.default.pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// elements_view() requires default_initializable = default; + +#include +#include +#include +#include + +template +struct View : cuda::std::ranges::view_base { + int i = 42; + template = 0> + __host__ __device__ constexpr explicit View() noexcept {} + __host__ __device__ cuda::std::tuple* begin() const; + __host__ __device__ cuda::std::tuple* end() const; +}; + + +// clang-format off +static_assert( cuda::std::is_default_constructible_v, 0>>); +static_assert(!cuda::std::is_default_constructible_v, 0>>); +// clang-format on + +__host__ __device__ constexpr bool test() { + { + cuda::std::ranges::elements_view, 0> ev = {}; + assert(ev.base().i == 42); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/ctor.view.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/ctor.view.pass.cpp new file mode 100644 index 00000000000..bf9a4f8ec9c --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/ctor.view.pass.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr explicit elements_view(V base); + +#include +#include +#include +#include +#include + +#include "MoveOnly.h" + +struct View : cuda::std::ranges::view_base { + MoveOnly mo; + __host__ __device__ cuda::std::tuple* begin() const; + __host__ __device__ cuda::std::tuple* end() const; +}; + +// Test Explicit +static_assert(cuda::std::is_constructible_v, View>); +static_assert(!cuda::std::is_convertible_v>); + +__host__ __device__ constexpr bool test() { + { + cuda::std::ranges::elements_view ev{View{{}, MoveOnly{5}}}; + assert(cuda::std::move(ev).base().mo.get() == 5); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/end.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/end.pass.cpp new file mode 100644 index 00000000000..78603975449 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/end.pass.cpp @@ -0,0 +1,162 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr auto end() requires (!simple-view && !common_range) +// constexpr auto end() requires (!simple-view && common_range) +// constexpr auto end() const requires range +// constexpr auto end() const requires common_range + +#include +#include +#include +#include +#include + +#include "types.h" + +// | simple | common | v.end() | as_const(v) +// | | | | .end() +// |--------|--------|------------------|--------------- +// | Y | Y | iterator | iterator +// | Y | N | sentinel | sentinel +// | N | Y | iterator | iterator +// | N | N | sentinel | sentinel + +// !range +#if TEST_STD_VER > 17 +template +concept HasEnd = requires(T t) { t.end(); }; + +template +concept HasConstEnd = requires(const T ct) { ct.end(); }; +#else +template +inline constexpr bool HasEnd = false; + +template +inline constexpr bool HasEnd().end())>> = true; + +template +inline constexpr bool HasConstEnd = false; + +template +inline constexpr bool HasConstEnd().end())>> = true; +#endif + +struct NoConstEndView : TupleBufferView { +#if defined(TEST_COMPILER_NVRTC) // nvbug 3961621 + template + __host__ __device__ constexpr NoConstEndView(T&& input) : TupleBufferView(cuda::std::forward(input)) {} +#else + using TupleBufferView::TupleBufferView; +#endif + __host__ __device__ constexpr cuda::std::tuple* begin() { return buffer_; } + __host__ __device__ constexpr cuda::std::tuple* end() { return buffer_ + size_; } +}; + +static_assert(HasEnd>); +static_assert(!HasConstEnd>); + +__host__ __device__ constexpr bool test() { + cuda::std::tuple buffer[] = {{1}, {2}, {3}}; + + // simple-view && common_view + { + SimpleCommon v{buffer}; + auto ev = cuda::std::views::elements<0>(v); + + auto it = ev.begin(); + decltype(auto) st = ev.end(); + assert(st == it + 3); + + auto const_it = cuda::std::as_const(ev).begin(); + decltype(auto) const_st = cuda::std::as_const(ev).end(); + assert(const_st == const_it + 3); + + // Both iterator + static_assert(cuda::std::same_as); + static_assert(cuda::std::same_as); + static_assert(cuda::std::same_as); + } + + // simple-view && !common_view + { + SimpleNonCommon v{buffer}; + auto ev = cuda::std::views::elements<0>(v); + + auto it = ev.begin(); + decltype(auto) st = ev.end(); + assert(st == it + 3); + + auto const_it = cuda::std::as_const(ev).begin(); + decltype(auto) const_st = cuda::std::as_const(ev).end(); + assert(const_st == const_it + 3); + + // Both iterator + static_assert(cuda::std::same_as); + static_assert(!cuda::std::same_as); + static_assert(!cuda::std::same_as); + } + + // !simple-view && common_view + { + NonSimpleCommon v{buffer}; + auto ev = cuda::std::views::elements<0>(v); + + auto it = ev.begin(); + decltype(auto) st = ev.end(); + assert(st == it + 3); + + auto const_it = cuda::std::as_const(ev).begin(); + decltype(auto) const_st = cuda::std::as_const(ev).end(); + assert(const_st == const_it + 3); + + // iterator and iterator + static_assert(!cuda::std::same_as); + static_assert(cuda::std::same_as); + static_assert(cuda::std::same_as); + } + + // !simple-view && !common_view + { + NonSimpleNonCommon v{buffer}; + auto ev = cuda::std::views::elements<0>(v); + + auto it = ev.begin(); + decltype(auto) st = ev.end(); + assert(st == it + 3); + + auto const_it = cuda::std::as_const(ev).begin(); + decltype(auto) const_st = cuda::std::as_const(ev).end(); + assert(const_st == const_it + 3); + + // sentinel and sentinel + static_assert(!cuda::std::same_as); + static_assert(!cuda::std::same_as); + static_assert(!cuda::std::same_as); + } + + // LWG 3406 elements_view::begin() and elements_view::end() have incompatible constraints + { + cuda::std::tuple x[] = {{0, 0}}; + cuda::std::ranges::subrange r = {cuda::std::counted_iterator(x, 1), cuda::std::default_sentinel}; + auto v = r | cuda::std::views::elements<0>; + assert(v.begin() != v.end()); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/arithmetic.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/arithmetic.pass.cpp new file mode 100644 index 00000000000..514bf56e431 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/arithmetic.pass.cpp @@ -0,0 +1,151 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr iterator& operator+=(difference_type n) +// requires random_access_range; +// +// constexpr iterator& operator-=(difference_type n) +// requires random_access_range; +// +// friend constexpr iterator operator+(const iterator& x, difference_type y) +// requires random_access_range; +// +// friend constexpr iterator operator+(difference_type x, const iterator& y) +// requires random_access_range; +// +// friend constexpr iterator operator-(const iterator& x, difference_type y) +// requires random_access_range; +// +// friend constexpr difference_type operator-(const iterator& x, const iterator& y) +// requires sized_sentinel_for, iterator_t>; + +#include + +#include + +#include "test_macros.h" +#include "test_iterators.h" + +#if TEST_STD_VER > 17 +template +concept CanPlus = requires(T t, U u) { t + u; }; + +template +concept CanPlusEqual = requires(T t, U u) { t += u; }; + +template +concept CanMinus = requires(T t, U u) { t - u; }; + +template +concept CanMinusEqual = requires(T t, U u) { t -= u; }; +#else +template +constexpr bool CanPlus = false; + +template +constexpr bool CanPlus() + cuda::std::declval())>> = true; + +template +constexpr bool CanPlusEqual = false; + +template +constexpr bool CanPlusEqual() += cuda::std::declval())>> = true; + +template +constexpr bool CanMinus = false; + +template +constexpr bool CanMinus() - cuda::std::declval())>> = true; + +template +constexpr bool CanMinusEqual = false; + +template +constexpr bool CanMinusEqual() -= cuda::std::declval())>> = true; +#endif + +template +using ElemIter = cuda::std::ranges::iterator_t>; + +using RandomAccessRange = cuda::std::ranges::subrange*>; +static_assert(cuda::std::ranges::random_access_range); +static_assert(cuda::std::sized_sentinel_for, // + cuda::std::ranges::iterator_t>); + +static_assert(CanPlus, int>); +static_assert(CanPlus>); +static_assert(CanPlusEqual, int>); +static_assert(CanMinus, int>); +static_assert(CanMinus, ElemIter>); +static_assert(CanMinusEqual, int>); + +using BidiRange = cuda::std::ranges::subrange*>>; +static_assert(!cuda::std::ranges::random_access_range); +static_assert(!cuda::std::sized_sentinel_for, // + cuda::std::ranges::iterator_t>); + +static_assert(!CanPlus, int>); +static_assert(!CanPlus>); +static_assert(!CanPlusEqual, int>); +static_assert(!CanMinus, int>); +static_assert(!CanMinus, ElemIter>); +static_assert(!CanMinusEqual, int>); + + __host__ __device__ constexpr bool test() { + cuda::std::tuple ts[] = {{1}, {2}, {3}, {4}}; + + RandomAccessRange r{&ts[0], &ts[0] + 4}; + auto ev = r | cuda::std::views::elements<0>; + { + // operator+(x, n) operator+(n,x) and operator+= + auto it1 = ev.begin(); + + auto it2 = it1 + 3; + assert(it2.base() == &ts[3]); + + auto it3 = 3 + it1; + assert(it3.base() == &ts[3]); + + it1 += 3; + assert(it1 == it2); + assert(it1.base() == &ts[3]); + } + + { + // operator-(x, n) and operator-= + auto it1 = ev.end(); + + auto it2 = it1 - 3; + assert(it2.base() == &ts[1]); + + it1 -= 3; + assert(it1 == it2); + assert(it1.base() == &ts[1]); + } + + { + // operator-(x, y) + assert((ev.end() - ev.begin()) == 4); + + auto it1 = ev.begin() + 2; + auto it2 = ev.end() - 1; + assert((it1 - it2) == -1); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp new file mode 100644 index 00000000000..57ce07c5e9c --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp @@ -0,0 +1,110 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr const iterator_t& base() const & noexcept; +// constexpr iterator_t base() &&; + +#include +#include +#include +#include +#include + +#include "test_macros.h" +#include "MoveOnly.h" +#include "../types.h" + +// Test Noexcept +#if TEST_STD_VER > 17 +template +concept IsBaseNoexcept = requires { { cuda::std::declval().base() } noexcept; }; +#else +template +inline constexpr bool IsBaseNoexcept = false; + +template +inline constexpr bool IsBaseNoexcept().base())>> = noexcept(cuda::std::declval().base()); +#endif + +using BaseView = cuda::std::ranges::subrange*>; +using ElementsIter = cuda::std::ranges::iterator_t>; + +static_assert(IsBaseNoexcept); +static_assert(IsBaseNoexcept); +static_assert(IsBaseNoexcept); +static_assert(!IsBaseNoexcept); + +struct MoveOnlyIter : IterBase { + MoveOnly mo; +}; +struct Sent { + __host__ __device__ friend constexpr bool operator==(const Sent&, const MoveOnlyIter&) { return true; } +#if TEST_STD_VER < 20 + __host__ __device__ friend constexpr bool operator==(const MoveOnlyIter&, const Sent&) { return true; } + __host__ __device__ friend constexpr bool operator!=(const Sent&, const MoveOnlyIter&) { return false; } + __host__ __device__ friend constexpr bool operator!=(const MoveOnlyIter&, const Sent&) { return false; } +#endif +}; + +__host__ __device__ constexpr bool test() { + cuda::std::tuple t{5}; + + // const & + { + const ElementsIter it{&t}; + decltype(auto) base = it.base(); + static_assert(cuda::std::is_same_v* const&>); + assert(base == &t); + } + + // & + { + ElementsIter it{&t}; + decltype(auto) base = it.base(); + static_assert(cuda::std::is_same_v* const&>); + assert(base == &t); + } + + // && + { + ElementsIter it{&t}; + decltype(auto) base = cuda::std::move(it).base(); + static_assert(cuda::std::is_same_v*>); + assert(base == &t); + } + + // const && + { + const ElementsIter it{&t}; + decltype(auto) base = cuda::std::move(it).base(); + static_assert(cuda::std::is_same_v* const&>); + assert(base == &t); + } + + // move only + { + using MoveOnlyElemIter = + cuda::std::ranges::iterator_t, 0>>; + + MoveOnlyElemIter it{MoveOnlyIter{{}, MoveOnly{5}}}; + decltype(auto) base = cuda::std::move(it).base(); + static_assert(cuda::std::is_same_v); + assert(base.mo.get() == 5); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp new file mode 100644 index 00000000000..35af1b1027a --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/compare.pass.cpp @@ -0,0 +1,167 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// friend constexpr bool operator==(const iterator& x, const iterator& y) +// requires equality_comparable>; +// friend constexpr bool operator<(const iterator& x, const iterator& y) +// requires random_access_range; +// friend constexpr bool operator>(const iterator& x, const iterator& y) +// requires random_access_range; +// friend constexpr bool operator<=(const iterator& x, const iterator& y) +// requires random_access_range; +// friend constexpr bool operator>=(const iterator& x, const iterator& y) +// requires random_access_range; +// friend constexpr auto operator<=>(const iterator& x, const iterator& y) +// requires random_access_range && three_way_comparable>; + +#include +#include +#include +#ifndef _LIBCUDACXX_HAS_NO_SPACESHIP_OPERATOR +#include +#endif + +#include "test_macros.h" +#include "test_iterators.h" + +template +__host__ __device__ constexpr void compareOperatorTest(const Iter1& iter1, const Iter2& iter2) { + assert(!(iter1 < iter1)); + assert(iter1 < iter2); + assert(!(iter2 < iter1)); + + assert(iter1 <= iter1); + assert(iter1 <= iter2); + assert(!(iter2 <= iter1)); + + assert(!(iter1 > iter1)); + assert(!(iter1 > iter2)); + assert(iter2 > iter1); + + assert(iter1 >= iter1); + assert(!(iter1 >= iter2)); + assert(iter2 >= iter1); + + assert(iter1 == iter1); + assert(!(iter1 == iter2)); + assert(iter2 == iter2); + + assert(!(iter1 != iter1)); + assert(iter1 != iter2); + assert(!(iter2 != iter2)); +} + +template +__host__ __device__ constexpr void inequalityOperatorsDoNotExistTest(const Iter1& iter1, const Iter2& iter2) { + static_assert(!cuda::std::is_invocable_v, Iter1, Iter2>); + static_assert(!cuda::std::is_invocable_v, Iter1, Iter2>); + static_assert(!cuda::std::is_invocable_v, Iter1, Iter2>); + static_assert(!cuda::std::is_invocable_v, Iter1, Iter2>); +} + +__host__ __device__ constexpr bool test() { + cuda::std::tuple ts[] = {{1}, {2}, {3}}; + +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR + { + // Test a new-school iterator with operator<=>; the iterator should also have operator<=>. + using It = three_way_contiguous_iterator*>; + using Subrange = cuda::std::ranges::subrange; + static_assert(cuda::std::three_way_comparable); + using R = cuda::std::ranges::elements_view; + static_assert(cuda::std::three_way_comparable>); + + auto ev = Subrange{It{&ts[0]}, It{&ts[0] + 3}} | cuda::std::views::elements<0>; + auto iter1 = ev.begin(); + auto iter2 = iter1 + 1; + + compareOperatorTest(iter1, iter2); + + assert((iter1 <=> iter2) == cuda::std::strong_ordering::less); + assert((iter1 <=> iter1) == cuda::std::strong_ordering::equal); + assert((iter2 <=> iter1) == cuda::std::strong_ordering::greater); + } +#endif + + { + // Test an old-school iterator with no operator<=>; the elements view iterator shouldn't have + // operator<=> either. + using It = random_access_iterator*>; + using Subrange = cuda::std::ranges::subrange; +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR + static_assert(!cuda::std::three_way_comparable); + using R = cuda::std::ranges::elements_view; + static_assert(!cuda::std::three_way_comparable>); +#endif + + auto ev = Subrange{It{&ts[0]}, It{&ts[0] + 3}} | cuda::std::views::elements<0>; + auto iter1 = ev.begin(); + auto iter2 = iter1 + 1; + + compareOperatorTest(iter1, iter2); + } + + { + // non random_access_range + using It = bidirectional_iterator*>; + using Subrange = cuda::std::ranges::subrange; +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR + static_assert(!cuda::std::ranges::random_access_range); + using R = cuda::std::ranges::elements_view; + static_assert(!cuda::std::three_way_comparable>); +#endif + + auto ev = Subrange{It{&ts[0]}, It{&ts[0] + 1}} | cuda::std::views::elements<0>; + + auto it1 = ev.begin(); + auto it2 = ev.end(); + + assert(it1 == it1); + assert(!(it1 != it1)); + assert(it2 == it2); + assert(!(it2 != it2)); + + assert(it1 != it2); + + ++it1; + assert(it1 == it2); + + inequalityOperatorsDoNotExistTest(it1, it2); + } + + { + // underlying iterator does not support == + using Iter = cpp20_input_iterator*>; + using Sent = sentinel_wrapper; + using Subrange = cuda::std::ranges::subrange; +#ifndef TEST_HAS_NO_SPACESHIP_OPERATOR + using R = cuda::std::ranges::elements_view; + static_assert(!cuda::std::three_way_comparable>); +#endif + + auto ev = Subrange{Iter{&ts[0]}, Sent{Iter{&ts[0] + 1}}} | cuda::std::views::elements<0>; + auto it = ev.begin(); + + using ElemIter = decltype(it); + static_assert(!cuda::std::invocable, ElemIter, ElemIter>); + static_assert(!cuda::std::invocable, ElemIter, ElemIter>); + inequalityOperatorsDoNotExistTest(it, it); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.pass.cpp new file mode 100644 index 00000000000..220dcbb99aa --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.base.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr explicit iterator(iterator_t current); + +#include +#include +#include + +#include "../types.h" + +// Test explicit +using BaseIter = cuda::std::tuple*; +using ElementsIter = cuda::std::ranges::iterator_t, 0>>; + +static_assert(cuda::std::is_constructible_v); +static_assert(!cuda::std::is_convertible_v); + +struct TracedMoveIter : IterBase{ + bool moved = false; + + constexpr TracedMoveIter() = default; + constexpr TracedMoveIter(const TracedMoveIter&) = default; + __host__ __device__ constexpr TracedMoveIter(TracedMoveIter&&) : moved{true} {} + constexpr TracedMoveIter& operator=(TracedMoveIter&&) = default; + constexpr TracedMoveIter& operator=(const TracedMoveIter&) = default; +}; + +struct TracedMoveView : cuda::std::ranges::view_base { + __host__ __device__ TracedMoveIter begin() const { return TracedMoveIter{}; } + __host__ __device__ TracedMoveIter end() const { return TracedMoveIter{}; } +}; + +__host__ __device__ constexpr bool test() { + using Iter = cuda::std::ranges::iterator_t>; + Iter iter{TracedMoveIter{}}; + assert(iter.base().moved); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.default.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.default.pass.cpp new file mode 100644 index 00000000000..1c0794ae43a --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.default.pass.cpp @@ -0,0 +1,59 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// iterator() requires default_initializable> = default; + +#include +#include + +#include "../types.h" + +struct PODIter : IterBase { + int i; // deliberately uninitialised +}; + +struct IterDefaultCtrView : cuda::std::ranges::view_base { + __host__ __device__ PODIter begin() const { return PODIter{}; } + __host__ __device__ PODIter end() const { return PODIter{}; } +}; + +struct IterNoDefaultCtrView : cuda::std::ranges::view_base { + __host__ __device__ cpp20_input_iterator*> begin() const { return cpp20_input_iterator*>{nullptr}; } + __host__ __device__ sentinel_wrapper*>> end() const { return sentinel_wrapper*>>{}; } +}; + +template +using ElementsIter = cuda::std::ranges::iterator_t>; + +static_assert(!cuda::std::default_initializable>); +static_assert(cuda::std::default_initializable>); + +__host__ __device__ constexpr bool test() { + using Iter = ElementsIter; + { + Iter iter; + assert(iter.base().i == 0); // PODIter has to be initialised to have value 0 + } + + { + Iter iter = {}; + assert(iter.base().i == 0); // PODIter has to be initialised to have value 0 + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp new file mode 100644 index 00000000000..b2063be238e --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/ctor.other.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr iterator(iterator i) +// requires Const && convertible_to, iterator_t>; + +#include +#include +#include + +#include "../types.h" + +template +struct ConvertibleIter : IterBase> { + using iterator_category = cuda::std::random_access_iterator_tag; + using value_type = cuda::std::tuple; + using difference_type = intptr_t; + + bool movedFromOtherConst = false; + int i = 0; + + constexpr ConvertibleIter() = default; + __host__ __device__ constexpr ConvertibleIter(int ii) : i(ii) {} + template = 0> + __host__ __device__ constexpr ConvertibleIter(ConvertibleIter it) : movedFromOtherConst(true), i(it.i) {} +}; + +template +struct BasicView : cuda::std::ranges::view_base { + __host__ __device__ Iter begin() { return Iter{}; } + __host__ __device__ Iter end() { return Iter{}; } + + __host__ __device__ ConstIter begin() const { return ConstIter{}; } + __host__ __device__ ConstIter end() const { return ConstIter{}; } +}; + +template +using ElemIter = cuda::std::ranges::iterator_t>; + +template +using ConstElemIter = cuda::std::ranges::iterator_t>; + +using ConvertibleView = BasicView, ConvertibleIter>; +using NonConvertibleView = BasicView*>, bidirectional_iterator*>>; + +static_assert(cuda::std::is_constructible_v, ElemIter>); +static_assert(!cuda::std::is_constructible_v, ConstElemIter>); +static_assert(!cuda::std::is_constructible_v, ElemIter>); +static_assert(!cuda::std::is_constructible_v, ConstElemIter>); + +__host__ __device__ constexpr bool test() { + ElemIter iter{ConvertibleIter{5}}; + ConstElemIter constIter = iter; // implicit + assert(constIter.base().movedFromOtherConst); + assert(constIter.base().i == 5); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/decrement.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/decrement.pass.cpp new file mode 100644 index 00000000000..f48c98f8e80 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/decrement.pass.cpp @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr iterator& operator--() requires bidirectional_range; +// constexpr iterator operator--(int) requires bidirectional_range; + +#include +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" + +#if TEST_STD_VER > 17 +template +concept CanPreDecrement = requires(T& t) { --t; }; + +template +concept CanPostDecrement = requires(T& t) { t--; }; +#else +template +inline constexpr bool CanPreDecrement = false; + +template +inline constexpr bool CanPreDecrement())>> = true; + +template +inline constexpr bool CanPostDecrement = false; + +template +inline constexpr bool CanPostDecrement()--)>> = true; +#endif + +template > +__host__ __device__ constexpr void testOne() { + using Range = cuda::std::ranges::subrange; + cuda::std::tuple ts[] = {{1}, {2}, {3}}; + auto ev = Range{Iter{&ts[0]}, Sent{Iter{&ts[0] + 3}}} | cuda::std::views::elements<0>; + + using ElementIter = cuda::std::ranges::iterator_t; + + if constexpr (!cuda::std::bidirectional_iterator) { + auto it = ev.begin(); + static_assert(!CanPreDecrement); + static_assert(!CanPostDecrement); + } else { + // --i + { + auto it = ev.begin(); + static_assert(CanPreDecrement); + + ++it; + assert(base(it.base()) == &ts[1]); + + decltype(auto) result = --it; + + static_assert(cuda::std::is_same_v); + assert(&result == &it); + + assert(base(it.base()) == &ts[0]); + } + + // i-- + { + auto it = ev.begin(); + static_assert(CanPostDecrement); + + ++it; + assert(base(it.base()) == &ts[1]); + + decltype(auto) result = it--; + + static_assert(cuda::std::is_same_v); + + assert(base(it.base()) == &ts[0]); + assert(base(result.base()) == &ts[1]); + } + } +} + +__host__ __device__ constexpr bool test() { + using Ptr = cuda::std::tuple*; + testOne>(); + testOne>(); + testOne>(); + testOne>(); + testOne>(); + testOne(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/deref.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/deref.pass.cpp new file mode 100644 index 00000000000..94783e94dbb --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/deref.pass.cpp @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr decltype(auto) operator*() const; + +#include +#include +#include +#include +#include + +template +__host__ __device__ constexpr void testReference(T (&ts)[Size]) { + auto ev = ts | cuda::std::views::elements; + auto it = ev.begin(); + + decltype(auto) result = *it; + using ExpectedType = decltype(cuda::std::get(ts[0])); + static_assert(cuda::std::is_same_v); + + if constexpr (cuda::std::is_reference_v) { + // tuple/array/pair + assert(&result == &cuda::std::get(ts[0])); + } else { + // subrange + assert(result == cuda::std::get(ts[0])); + } +} + +// LWG 3502 elements_view should not be allowed to return dangling references +template +__host__ __device__ constexpr void testValue(T t) { + auto ev = cuda::std::views::iota(0, 1) | cuda::std::views::transform([&t](int) { return t; }) | cuda::std::views::elements; + auto it = ev.begin(); + + decltype(auto) result = *it; + using ExpectedType = cuda::std::remove_cvref_t(t))>; + static_assert(cuda::std::is_same_v); + + assert(result == cuda::std::get(t)); +} + +__host__ __device__ constexpr bool test() { + // test tuple + { + cuda::std::tuple ts[] = {{1, short(2), 3}, {4, short(5), 6}}; + testReference<0>(ts); + testReference<1>(ts); + testReference<2>(ts); + testValue<0>(ts[0]); + testValue<1>(ts[0]); + testValue<2>(ts[0]); + } + + // test pair + { + cuda::std::pair ps[] = {{1, short(2)}, {4, short(5)}}; + testReference<0>(ps); + testReference<1>(ps); + testValue<0>(ps[0]); + testValue<1>(ps[0]); + } + + // test array + { + cuda::std::array arrs[] = {{1, 2, 3}, {3, 4, 5}}; + testReference<0>(arrs); + testReference<1>(arrs); + testReference<2>(arrs); + testValue<0>(arrs[0]); + testValue<1>(arrs[0]); + testValue<2>(arrs[0]); + } + + // test subrange + { + int i = 5; + cuda::std::ranges::subrange srs[] = {{&i, &i}, {&i, &i}}; + testReference<0>(srs); + testReference<1>(srs); + testValue<0>(srs[0]); + testValue<1>(srs[0]); + } + + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER > 17 + static_assert(test()); +#endif + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/increment.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/increment.pass.cpp new file mode 100644 index 00000000000..d6dd08875b4 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/increment.pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr iterator& operator++(); +// constexpr void operator++(int); +// constexpr iterator operator++(int) requires forward_range; + +#include +#include +#include +#include + +#include "test_iterators.h" + +template > +__host__ __device__ constexpr void testOne() { + using Range = cuda::std::ranges::subrange; + cuda::std::tuple ts[] = {{1}, {2}, {3}}; + auto ev = Range{Iter{&ts[0]}, Sent{Iter{&ts[0] + 3}}} | cuda::std::views::elements<0>; + + using ElementIter = cuda::std::ranges::iterator_t; + + // ++i + { + auto it = ev.begin(); + decltype(auto) result = ++it; + + static_assert(cuda::std::is_same_v); + assert(&result == &it); + + assert(base(it.base()) == &ts[1]); + } + + // i++ + { + if constexpr (cuda::std::forward_iterator) { + auto it = ev.begin(); + decltype(auto) result = it++; + + static_assert(cuda::std::is_same_v); + + assert(base(it.base()) == &ts[1]); + assert(base(result.base()) == &ts[0]); + } else { + auto it = ev.begin(); + it++; + + static_assert(cuda::std::is_same_v); + assert(base(it.base()) == &ts[1]); + } + } +} + +__host__ __device__ constexpr bool test() { + using Ptr = cuda::std::tuple*; + testOne>(); + testOne>(); + testOne>(); + testOne>(); + testOne>(); + testOne(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/member_types.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/member_types.compile.pass.cpp new file mode 100644 index 00000000000..6bba622f675 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/member_types.compile.pass.cpp @@ -0,0 +1,107 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// Member typedefs in elements_view::iterator. + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" + +template +using Range = cuda::std::ranges::subrange>; + +template +using ElementsIter = cuda::std::ranges::iterator_t>; + +// using iterator_concept = see below; +static_assert(cuda::std::same_as*>>>::iterator_concept, + cuda::std::input_iterator_tag>); + +static_assert(cuda::std::same_as*>>>::iterator_concept, // + cuda::std::forward_iterator_tag>); + +static_assert(cuda::std::same_as*>>>::iterator_concept, + cuda::std::bidirectional_iterator_tag>); + +static_assert(cuda::std::same_as*>>>::iterator_concept, + cuda::std::random_access_iterator_tag>); + +static_assert(cuda::std::same_as*>>>::iterator_concept, + cuda::std::random_access_iterator_tag>); + +static_assert(cuda::std::same_as*>>::iterator_concept, // + cuda::std::random_access_iterator_tag>); + +// using iterator_category = see below; // not always present +#if TEST_STD_VER > 17 +template +concept HasIterCategory = requires { typename T::iterator_category; }; +#else +template +inline constexpr bool HasIterCategory = false; + +template +inline constexpr bool HasIterCategory> = true; +#endif + +static_assert(!HasIterCategory*>>>>); +static_assert(HasIterCategory*>>>>); + +static_assert(cuda::std::same_as*>>>::iterator_category, + cuda::std::forward_iterator_tag>); + +static_assert(cuda::std::same_as*>>>::iterator_category, + cuda::std::bidirectional_iterator_tag>); + +static_assert(cuda::std::same_as*>>>::iterator_category, + cuda::std::random_access_iterator_tag>); + +static_assert(cuda::std::same_as*>>>::iterator_category, + cuda::std::random_access_iterator_tag>); + +static_assert(cuda::std::same_as*>>::iterator_category, // + cuda::std::random_access_iterator_tag>); + +struct ToPair { + __host__ __device__ constexpr auto operator()(int) const noexcept { + return cuda::std::pair{1, static_cast(1)}; + } +}; +using Generator = decltype(cuda::std::views::iota(0, 1) | cuda::std::views::transform(ToPair{})); +#ifndef TEST_COMPILER_NVCC_BELOW_11_3 +static_assert(cuda::std::ranges::random_access_range); +#endif // !TEST_COMPILER_NVCC_BELOW_11_3 + +static_assert(cuda::std::same_as::iterator_category, // + cuda::std::input_iterator_tag>); + +// using value_type = remove_cvref_t>>; +static_assert(cuda::std::same_as*>, 0>::value_type, int>); + +static_assert(cuda::std::same_as*>, 1>::value_type, long>); + +static_assert(cuda::std::same_as::value_type, int>); + +static_assert(cuda::std::same_as::value_type, short>); + +// using difference_type = range_difference_t; +static_assert(cuda::std::same_as*>>::difference_type, + cuda::std::ranges::range_difference_t*>>>); + +static_assert(cuda::std::same_as::difference_type, // + cuda::std::ranges::range_difference_t>); + +int main(int, char**) { + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/subscript.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/subscript.pass.cpp new file mode 100644 index 00000000000..3e89db12dea --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/iterator/subscript.pass.cpp @@ -0,0 +1,81 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr decltype(auto) operator[](difference_type n) const +// requires random_access_range + +#include +#include +#include + +#include "test_macros.h" +#include "test_iterators.h" + +#if TEST_STD_VER > 17 +template +concept CanSubscript = requires(T t, U u) { t[u]; }; +#else +template +inline constexpr bool CanSubscript = false; + +template +inline constexpr bool CanSubscript()[cuda::std::declval()])>> = true; +#endif + +template +using ElemIter = cuda::std::ranges::iterator_t>; + +using RandomAccessRange = cuda::std::ranges::subrange*>; +static_assert(cuda::std::ranges::random_access_range); + +static_assert(CanSubscript, int>); + +using BidiRange = cuda::std::ranges::subrange*>>; +static_assert(!cuda::std::ranges::random_access_range); + +static_assert(!CanSubscript, int>); + +__host__ __device__ constexpr bool test() { + { + // reference + cuda::std::tuple ts[] = {{1}, {2}, {3}, {4}}; + auto ev = ts | cuda::std::views::elements<0>; + auto it = ev.begin(); + + assert(&it[0] == &*it); + assert(&it[2] == &*(it + 2)); + + static_assert(cuda::std::is_same_v); + } + + { + // value + auto ev = cuda::std::views::iota(0, 5) | cuda::std::views::transform([](int i) { return cuda::std::tuple{i}; }) | + cuda::std::views::elements<0>; + auto it = ev.begin(); + assert(it[0] == *it); + assert(it[2] == *(it + 2)); + assert(it[4] == *(it + 4)); + + static_assert(cuda::std::is_same_v); + } + + return true; +} + +int main(int, char**) { + test(); +#if TEST_STD_VER > 17 && defined(_LIBCUDACXX_ADDRESSOF) + static_assert(test()); +#endif // TEST_STD_VER > 17 && defined(_LIBCUDACXX_ADDRESSOF) + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp new file mode 100644 index 00000000000..95f86e03981 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/range.concept.compile.pass.cpp @@ -0,0 +1,92 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// concept checking +// +// template +// concept has-tuple-element = +// tuple-like && N < tuple_size_v; +// +// template +// concept returnable-element = +// is_reference_v || move_constructible>; +// +// template +// requires view && has-tuple-element, N> && +// has-tuple-element>, N> && +// returnable-element, N> +// class elements_view; + +#include +#include +#include +#include +#include + +#include "test_iterators.h" + +template +using Range = cuda::std::ranges::subrange>; + +#if TEST_STD_VER > 17 +template +concept HasElementsView = requires { typename cuda::std::ranges::elements_view; }; +#else +template +inline constexpr bool HasElementsView = false; + +template +inline constexpr bool HasElementsView>> = true; +#endif + +static_assert(HasElementsView*>, 0>); +static_assert(HasElementsView*>, 1>); +static_assert(HasElementsView*>, 2>); +static_assert(HasElementsView*>, 3>); + +// !view +static_assert(!cuda::std::ranges::view, 1>>); +static_assert(!HasElementsView, 1>, 0>); + +// !input_range +static_assert(!cuda::std::ranges::input_range*>>>); +static_assert(!HasElementsView*>>, 0>); + +// !tuple-like +LIBCPP_STATIC_ASSERT(!cuda::std::__tuple_like::value); +static_assert(!HasElementsView, 1>); + +// !(N < tuple_size_v) +static_assert(!(2 < cuda::std::tuple_size_v< cuda::std::pair>)); +static_assert(!HasElementsView*>, 2>); + +// ! (is_reference_v || move_constructible>) +struct NonMovable { + __host__ __device__ constexpr NonMovable(int) {} + NonMovable(NonMovable&&) = delete; +}; +static_assert(!cuda::std::move_constructible); + +struct ToPair { + __host__ __device__ constexpr auto operator()(int) const noexcept { + return cuda::std::pair{1, 1}; + } +}; + +using NonMovableGenerator = + decltype(cuda::std::views::iota(0, 1) | cuda::std::views::transform(ToPair{})); + +static_assert(!HasElementsView); +static_assert(HasElementsView); + +int main(int, char**) { + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp new file mode 100644 index 00000000000..532e80ebb9e --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/base.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr sentinel_t base() const; + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +struct Sent { + int i; + + __host__ __device__ friend constexpr bool operator==(cuda::std::tuple*, const Sent&) { return true; } +#if TEST_STD_VER < 20 + __host__ __device__ friend constexpr bool operator==(const Sent&, cuda::std::tuple*) { return true; } + __host__ __device__ friend constexpr bool operator!=(cuda::std::tuple*, const Sent&) { return false; } + __host__ __device__ friend constexpr bool operator!=(const Sent&, cuda::std::tuple*) { return false; } +#endif +}; + +__host__ __device__ constexpr bool test() { + using BaseRange = cuda::std::ranges::subrange*, Sent>; + using EleRange = cuda::std::ranges::elements_view; + using EleSent = cuda::std::ranges::sentinel_t; + + const EleSent st{Sent{5}}; + decltype(auto) base = st.base(); + static_assert(cuda::std::same_as); + assert(base.i == 5); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.pass.cpp new file mode 100644 index 00000000000..8a4015edf28 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.base.pass.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr explicit sentinel(sentinel_t end); + +#include +#include +#include +#include + +#include "test_macros.h" + +struct Sent { + int i; + + __host__ __device__ friend constexpr bool operator==(cuda::std::tuple*, const Sent&) { return true; } +#if TEST_STD_VER < 20 + __host__ __device__ friend constexpr bool operator==(const Sent&, cuda::std::tuple*) { return true; } + __host__ __device__ friend constexpr bool operator!=(cuda::std::tuple*, const Sent&) { return false; } + __host__ __device__ friend constexpr bool operator!=(const Sent&, cuda::std::tuple*) { return false; } +#endif +}; + +struct Range : cuda::std::ranges::view_base { + __host__ __device__ cuda::std::tuple* begin() const { return nullptr; } + __host__ __device__ Sent end() { return Sent{}; } +}; + +// Test explicit + +static_assert(cuda::std::is_constructible_v>, Sent>); +static_assert(!cuda::std::is_convertible_v>>); + +__host__ __device__ constexpr bool test() { + // base is init correctly + { + using R = cuda::std::ranges::elements_view; + using Sentinel = cuda::std::ranges::sentinel_t; + + Sentinel s1(Sent{5}); + assert(s1.base().i == 5); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp new file mode 100644 index 00000000000..975e68e7bf1 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.convert.pass.cpp @@ -0,0 +1,105 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// constexpr sentinel(sentinel s) +// requires Const && convertible_to, sentinel_t>; + +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +struct Sent { + int i; + Sent() = default; + __host__ __device__ constexpr Sent(int ii) : i(ii) {} + __host__ __device__ friend constexpr bool operator==(cuda::std::tuple*, const Sent&) { return true; } +#if TEST_STD_VER < 20 + __host__ __device__ friend constexpr bool operator==(const Sent&, cuda::std::tuple*) { return true; } + __host__ __device__ friend constexpr bool operator!=(cuda::std::tuple*, const Sent&) { return false; } + __host__ __device__ friend constexpr bool operator!=(const Sent&, cuda::std::tuple*) { return false; } +#endif +}; + +struct ConstSent { + int i; + ConstSent() = default; + __host__ __device__ constexpr ConstSent(int ii) : i(ii) {} + __host__ __device__ constexpr ConstSent(const Sent& s) : i(s.i) {} + __host__ __device__ friend constexpr bool operator==(cuda::std::tuple*, const ConstSent&) { return true; } +#if TEST_STD_VER < 20 + __host__ __device__ friend constexpr bool operator==(const ConstSent&, cuda::std::tuple*) { return true; } + __host__ __device__ friend constexpr bool operator!=(cuda::std::tuple*, const ConstSent&) { return false; } + __host__ __device__ friend constexpr bool operator!=(const ConstSent&, cuda::std::tuple*) { return false; } +#endif +}; + +struct Range : cuda::std::ranges::view_base { + __host__ __device__ cuda::std::tuple* begin() const { return nullptr; } + __host__ __device__ Sent end() { return Sent{}; } + __host__ __device__ ConstSent end() const { return ConstSent{}; } +}; + +struct NonConvertConstSent { + int i; + NonConvertConstSent() = default; + __host__ __device__ constexpr NonConvertConstSent(int ii) : i(ii) {} + __host__ __device__ friend constexpr bool operator==(cuda::std::tuple*, const NonConvertConstSent&) { return true; } +#if TEST_STD_VER < 20 + __host__ __device__ friend constexpr bool operator==(const NonConvertConstSent&, cuda::std::tuple*) { return true; } + __host__ __device__ friend constexpr bool operator!=(cuda::std::tuple*, const NonConvertConstSent&) { return false; } + __host__ __device__ friend constexpr bool operator!=(const NonConvertConstSent&, cuda::std::tuple*) { return false; } +#endif +}; + +struct NonConvertConstSentRange : cuda::std::ranges::view_base { + __host__ __device__ cuda::std::tuple* begin() const { return nullptr; } + __host__ __device__ Sent end() { return Sent{}; } + __host__ __device__ NonConvertConstSent end() const { return NonConvertConstSent{}; } +}; + +// Test Constraint +static_assert(cuda::std::is_constructible_v>, + cuda::std::ranges::sentinel_t>>); + +// !Const +static_assert(!cuda::std::is_constructible_v>, + cuda::std::ranges::sentinel_t>>); + +// !convertible_to, sentinel_t> +static_assert(!cuda::std::is_constructible_v< + cuda::std::ranges::sentinel_t>, + cuda::std::ranges::sentinel_t>>); + +__host__ __device__ constexpr bool test() { + // base is init correctly + { + using R = cuda::std::ranges::elements_view; + using Sentinel = cuda::std::ranges::sentinel_t; + using ConstSentinel = cuda::std::ranges::sentinel_t; + static_assert(!cuda::std::same_as); + + Sentinel s1(Sent{5}); + ConstSentinel s2 = s1; + assert(s2.base().i == 5); + } + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.default.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.default.pass.cpp new file mode 100644 index 00000000000..c0473b1f937 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/ctor.default.pass.cpp @@ -0,0 +1,57 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// sentinel() = default; + +#include +#include +#include + +#include "test_macros.h" + +struct PODSentinel { + int i; // deliberately uninitialised + + __host__ __device__ friend constexpr bool operator==(cuda::std::tuple*, const PODSentinel&) { return true; } +#if TEST_STD_VER < 20 + __host__ __device__ friend constexpr bool operator==(const PODSentinel&, cuda::std::tuple*) { return true; } + __host__ __device__ friend constexpr bool operator!=(cuda::std::tuple*, const PODSentinel&) { return false; } + __host__ __device__ friend constexpr bool operator!=(const PODSentinel&, cuda::std::tuple*) { return false; } +#endif +}; + +struct Range : cuda::std::ranges::view_base { + __host__ __device__ cuda::std::tuple* begin() const { return nullptr; } + __host__ __device__ PODSentinel end() { return PODSentinel{}; } +}; + +__host__ __device__ constexpr bool test() { + using EleView = cuda::std::ranges::elements_view; + using Sentinel = cuda::std::ranges::sentinel_t; + static_assert(!cuda::std::is_same_v>); + + { + Sentinel s; + assert(s.base().i == 0); + } + { + Sentinel s = {}; + assert(s.base().i == 0); + } + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp new file mode 100644 index 00000000000..16ec1a256d9 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/ranges/range.adaptors/range.elements/sentinel/equality.pass.cpp @@ -0,0 +1,214 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14 + +// template +// requires sentinel_for, iterator_t>> +// friend constexpr bool operator==(const iterator& x, const sentinel& y); + +#include +#include +#include + +#include "test_macros.h" +#include "../types.h" + +template +struct Iter { + cuda::std::tuple* it_; + + using value_type = cuda::std::tuple; + using difference_type = intptr_t; + using iterator_concept = cuda::std::input_iterator_tag; + + __host__ __device__ constexpr decltype(auto) operator*() const { return *it_; } + __host__ __device__ constexpr Iter& operator++() { + ++it_; + return *this; + } + __host__ __device__ constexpr void operator++(int) { ++it_; } +}; + +template +struct Sent { + cuda::std::tuple* end_; + + __host__ __device__ friend constexpr bool operator==(const Sent& s, const Iter& i) { return i.it_ == s.end_; } +#if TEST_STD_VER < 20 + __host__ __device__ friend constexpr bool operator==(const Iter& i, const Sent& s) { return i.it_ == s.end_; } + __host__ __device__ friend constexpr bool operator!=(const Sent& s, const Iter& i) { return i.it_ != s.end_; } + __host__ __device__ friend constexpr bool operator!=(const Iter& i, const Sent& s) { return i.it_ != s.end_; } +#endif +}; + +template +struct CrossComparableSent { + cuda::std::tuple* end_; + + template + __host__ __device__ friend constexpr bool operator==(const CrossComparableSent& s, const Iter& i) { return i.it_ == s.end_; } +#if TEST_STD_VER < 20 + template + __host__ __device__ friend constexpr bool operator==(const Iter& i, const CrossComparableSent& s) { return i.it_ == s.end_; } + template + __host__ __device__ friend constexpr bool operator!=(const CrossComparableSent& s, const Iter& i) { return i.it_ != s.end_; } + template + __host__ __device__ friend constexpr bool operator!=(const Iter& i, const CrossComparableSent& s) { return i.it_ != s.end_; } +#endif +}; + +template