diff --git a/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.compile.pass.cpp new file mode 100644 index 0000000000..1b5000f597 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.compile.pass.cpp @@ -0,0 +1,51 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// concept permutable = see below; // Since C++20 + +#include + +#include "test_iterators.h" + +using AllConstraintsSatisfied = forward_iterator; +static_assert( cuda::std::forward_iterator); +static_assert( cuda::std::indirectly_movable_storable); +static_assert( cuda::std::indirectly_swappable); +static_assert( cuda::std::permutable); + +using NotAForwardIterator = cpp20_input_iterator; +static_assert(!cuda::std::forward_iterator); +static_assert( cuda::std::indirectly_movable_storable); +static_assert( cuda::std::indirectly_swappable); +static_assert(!cuda::std::permutable); + +struct NonCopyable { + NonCopyable(const NonCopyable&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; + __host__ __device__ friend void swap(NonCopyable&, NonCopyable&); +}; +using NotIMS = forward_iterator; + +static_assert( cuda::std::forward_iterator); +static_assert(!cuda::std::indirectly_movable_storable); +static_assert( cuda::std::indirectly_swappable); +static_assert(!cuda::std::permutable); + +// Note: it is impossible for an iterator to satisfy `indirectly_movable_storable` but not `indirectly_swappable`: +// `indirectly_swappable` requires both iterators to be `indirectly_readable` and for `ranges::iter_swap` to be +// well-formed for both iterators. `indirectly_movable_storable` also requires the iterator to be `indirectly_readable`. +// `ranges::iter_swap` is always defined for `indirectly_movable_storable` iterators. + +int main(int, char**) +{ + return 0; +} diff --git a/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.subsumption.compile.pass.cpp b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.subsumption.compile.pass.cpp new file mode 100644 index 0000000000..c88508bc33 --- /dev/null +++ b/libcudacxx/.upstream-tests/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.subsumption.compile.pass.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++17 + +// template +// concept permutable = see below; // Since C++20 + +#include + +template __host__ __device__ void test_subsumption() requires cuda::std::forward_iterator; +template __host__ __device__ void test_subsumption() requires cuda::std::indirectly_movable_storable; +template __host__ __device__ void test_subsumption() requires cuda::std::indirectly_swappable; +template __host__ __device__ constexpr bool test_subsumption() requires cuda::std::permutable { return true; } +static_assert(test_subsumption()); + +int main(int, char**) +{ + return 0; +} diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/CMakeLists.txt b/libcudacxx/include/cuda/std/detail/libcxx/include/CMakeLists.txt index 0593b4909b..74d3a74c7d 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/CMakeLists.txt +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/CMakeLists.txt @@ -102,6 +102,7 @@ set(files __iterator/next.h __iterator/ostream_iterator.h __iterator/ostreambuf_iterator.h + __iterator/permutable.h __iterator/prev.h __iterator/readable_traits.h __iterator/reverse_access.h diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/permutable.h b/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/permutable.h new file mode 100644 index 0000000000..2c751c6d0e --- /dev/null +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/__iterator/permutable.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCUDACXX___ITERATOR_PERMUTABLE_H +#define _LIBCUDACXX___ITERATOR_PERMUTABLE_H + +#ifndef __cuda_std__ +#include <__config> +#endif // __cuda_std__ + +#include "../__iterator/concepts.h" +#include "../__iterator/iter_swap.h" + +#if defined(_LIBCUDACXX_USE_PRAGMA_GCC_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCUDACXX_BEGIN_NAMESPACE_STD + +#if _LIBCUDACXX_STD_VER > 17 + +template +concept permutable = + forward_iterator<_Iterator> && + indirectly_movable_storable<_Iterator, _Iterator> && + indirectly_swappable<_Iterator, _Iterator>; + +#elif _LIBCUDACXX_STD_VER > 14 + +template +_LIBCUDACXX_CONCEPT_FRAGMENT( + __permutable_, + requires()( + requires(forward_iterator<_Iterator>), + requires(indirectly_movable_storable<_Iterator, _Iterator>), + requires(indirectly_swappable<_Iterator, _Iterator>) + )); + +template +_LIBCUDACXX_CONCEPT permutable = _LIBCUDACXX_FRAGMENT(__permutable_, _Iterator); + +#endif // _LIBCUDACXX_STD_VER > 14 + +_LIBCUDACXX_END_NAMESPACE_STD + +#endif // _LIBCUDACXX___ITERATOR_PERMUTABLE_H diff --git a/libcudacxx/include/cuda/std/detail/libcxx/include/iterator b/libcudacxx/include/cuda/std/detail/libcxx/include/iterator index 45830625dd..3e797f900d 100644 --- a/libcudacxx/include/cuda/std/detail/libcxx/include/iterator +++ b/libcudacxx/include/cuda/std/detail/libcxx/include/iterator @@ -702,6 +702,7 @@ template constexpr const E* data(initializer_list il) noexcept; #include "__iterator/next.h" #include "__iterator/ostream_iterator.h" #include "__iterator/ostreambuf_iterator.h" +#include "__iterator/permutable.h" #include "__iterator/prev.h" #include "__iterator/readable_traits.h" #include "__iterator/reverse_access.h" diff --git a/libcudacxx/libcxx/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.compile.pass.cpp b/libcudacxx/libcxx/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.compile.pass.cpp new file mode 100644 index 0000000000..54d5d46450 --- /dev/null +++ b/libcudacxx/libcxx/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.compile.pass.cpp @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// template +// concept permutable = see below; // Since C++20 + +#include + +#include "test_iterators.h" + +using AllConstraintsSatisfied = forward_iterator; +static_assert( std::forward_iterator); +static_assert( std::indirectly_movable_storable); +static_assert( std::indirectly_swappable); +static_assert( std::permutable); + +using NotAForwardIterator = cpp20_input_iterator; +static_assert(!std::forward_iterator); +static_assert( std::indirectly_movable_storable); +static_assert( std::indirectly_swappable); +static_assert(!std::permutable); + +struct NonCopyable { + NonCopyable(const NonCopyable&) = delete; + NonCopyable& operator=(const NonCopyable&) = delete; + friend void swap(NonCopyable&, NonCopyable&); +}; +using NotIMS = forward_iterator; + +static_assert( std::forward_iterator); +static_assert(!std::indirectly_movable_storable); +static_assert( std::indirectly_swappable); +static_assert(!std::permutable); + +// Note: it is impossible for an iterator to satisfy `indirectly_movable_storable` but not `indirectly_swappable`: +// `indirectly_swappable` requires both iterators to be `indirectly_readable` and for `ranges::iter_swap` to be +// well-formed for both iterators. `indirectly_movable_storable` also requires the iterator to be `indirectly_readable`. +// `ranges::iter_swap` is always defined for `indirectly_movable_storable` iterators. + +int main(int, char**) { + return 0; +} diff --git a/libcudacxx/libcxx/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.subsumption.compile.pass.cpp b/libcudacxx/libcxx/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.subsumption.compile.pass.cpp new file mode 100644 index 0000000000..9cd7f37f09 --- /dev/null +++ b/libcudacxx/libcxx/test/std/iterators/iterator.requirements/alg.req.permutable/permutable.subsumption.compile.pass.cpp @@ -0,0 +1,24 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// template +// concept permutable = see below; // Since C++20 + +#include + +template void test_subsumption() requires std::forward_iterator; +template void test_subsumption() requires std::indirectly_movable_storable; +template void test_subsumption() requires std::indirectly_swappable; +template constexpr bool test_subsumption() requires std::permutable { return true; } +static_assert(test_subsumption()); + +int main(int, char**) { + return 0; +}