diff --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv --- a/libcxx/docs/Status/RangesPaper.csv +++ b/libcxx/docs/Status/RangesPaper.csv @@ -17,7 +17,7 @@ | *no-throw-input-range* | *no-throw-forward-iterator* | *no-throw-forward-range*","| [iterator.concepts] -| [range.refinements]",Konstantin Varlamov,Not started +| [range.refinements]",Konstantin Varlamov,✅ `[specialized.algorithms] <http://wg21.link/specialized.algorithms>`_,"| ranges::uninitialized_default_construct | ranges::uninitialized_default_construct_n | ranges::uninitialized_value_construct diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -228,6 +228,7 @@ __memory/allocator.h __memory/auto_ptr.h __memory/compressed_pair.h + __memory/concepts.h __memory/construct_at.h __memory/pointer_traits.h __memory/raw_storage_iterator.h diff --git a/libcxx/include/__memory/concepts.h b/libcxx/include/__memory/concepts.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__memory/concepts.h @@ -0,0 +1,63 @@ +// -*- 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___MEMORY_CONCEPTS_H +#define _LIBCPP___MEMORY_CONCEPTS_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__ranges/access.h> +#include <__ranges/concepts.h> +#include <type_traits> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_RANGES) +namespace ranges { + +// [special.mem.concepts] + +// This concept ensures that uninitialized algorithms can construct an object +// at the address pointed-to by the iterator, which requires an lvalue. +template <class _Ip> +concept __nothrow_input_iterator = + input_iterator<_Ip> && + is_lvalue_reference_v<iter_reference_t<_Ip>> && + same_as<remove_cvref_t<iter_reference_t<_Ip>>, iter_value_t<_Ip>>; + +template <class _Sp, class _Ip> +concept __nothrow_sentinel_for = sentinel_for<_Sp, _Ip>; + +template <class _Rp> +concept __nothrow_input_range = + range<_Rp> && + __nothrow_input_iterator<iterator_t<_Rp>> && + __nothrow_sentinel_for<sentinel_t<_Rp>, iterator_t<_Rp>>; + +template <class _Ip> +concept __nothrow_forward_iterator = + __nothrow_input_iterator<_Ip> && + forward_iterator<_Ip> && + __nothrow_sentinel_for<_Ip, _Ip>; + +template <class _Rp> +concept __nothrow_forward_range = + __nothrow_input_range<_Rp> && + __nothrow_forward_iterator<iterator_t<_Rp>>; + +} // namespace ranges +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MEMORY_CONCEPTS_H diff --git a/libcxx/include/memory b/libcxx/include/memory --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -669,6 +669,7 @@ #include <__memory/allocator_arg_t.h> #include <__memory/allocator_traits.h> #include <__memory/compressed_pair.h> +#include <__memory/concepts.h> #include <__memory/construct_at.h> #include <__memory/pointer_traits.h> #include <__memory/raw_storage_iterator.h> diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -630,21 +630,22 @@ export * module __memory { - module addressof { private header "__memory/addressof.h" } - module allocation_guard { private header "__memory/allocation_guard.h" } - module allocator { private header "__memory/allocator.h" } - module allocator_arg_t { private header "__memory/allocator_arg_t.h" } - module allocator_traits { private header "__memory/allocator_traits.h" } - module auto_ptr { private header "__memory/auto_ptr.h" } - module compressed_pair { private header "__memory/compressed_pair.h" } - module construct_at { private header "__memory/construct_at.h" } - module pointer_traits { private header "__memory/pointer_traits.h" } - module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" } - module shared_ptr { private header "__memory/shared_ptr.h" } - module temporary_buffer { private header "__memory/temporary_buffer.h" } - module uninitialized_algorithms { private header "__memory/uninitialized_algorithms.h" } - module unique_ptr { private header "__memory/unique_ptr.h" } - module uses_allocator { private header "__memory/uses_allocator.h" } + module addressof { private header "__memory/addressof.h" } + module allocation_guard { private header "__memory/allocation_guard.h" } + module allocator { private header "__memory/allocator.h" } + module allocator_arg_t { private header "__memory/allocator_arg_t.h" } + module allocator_traits { private header "__memory/allocator_traits.h" } + module auto_ptr { private header "__memory/auto_ptr.h" } + module compressed_pair { private header "__memory/compressed_pair.h" } + module concepts { private header "__memory/concepts.h" } + module construct_at { private header "__memory/construct_at.h" } + module pointer_traits { private header "__memory/pointer_traits.h" } + module raw_storage_iterator { private header "__memory/raw_storage_iterator.h" } + module shared_ptr { private header "__memory/shared_ptr.h" } + module temporary_buffer { private header "__memory/temporary_buffer.h" } + module uninitialized_algorithms { private header "__memory/uninitialized_algorithms.h" } + module unique_ptr { private header "__memory/unique_ptr.h" } + module uses_allocator { private header "__memory/uses_allocator.h" } } } module mutex { diff --git a/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_forward_iterator.compile.pass.cpp b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_forward_iterator.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_forward_iterator.compile.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-concepts + +// template<class I> +// concept __nothrow_forward_iterator; + +#include <memory> + +#include "test_iterators.h" + +struct ForwardProxyIterator { + using value_type = int; + using difference_type = int; + ForwardProxyIterator& operator++(); + ForwardProxyIterator operator++(int); + bool operator==(const ForwardProxyIterator&) const; + + int operator*() const; +}; + +static_assert(std::ranges::__nothrow_forward_iterator<forward_iterator<int*>>); +static_assert(std::forward_iterator<ForwardProxyIterator>); +static_assert(!std::ranges::__nothrow_forward_iterator<ForwardProxyIterator>); diff --git a/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_forward_range.compile.pass.cpp b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_forward_range.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_forward_range.compile.pass.cpp @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-concepts + +// template<class R> +// concept __nothrow_forward_range; + +#include <memory> + +#include "test_iterators.h" +#include "test_range.h" + +// Has to be a template to work with `test_range`. +template <typename> +struct ForwardProxyIterator { + using value_type = int; + using difference_type = int; + ForwardProxyIterator& operator++(); + ForwardProxyIterator operator++(int); + bool operator==(const ForwardProxyIterator&) const; + + int operator*() const; +}; + +static_assert(std::ranges::__nothrow_forward_range<test_range<forward_iterator>>); +static_assert(!std::ranges::__nothrow_forward_range<test_range<cpp20_input_iterator>>); +static_assert(std::ranges::forward_range<test_range<ForwardProxyIterator>>); +static_assert(!std::ranges::__nothrow_forward_range<test_range<ForwardProxyIterator>>); diff --git a/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_input_iterator.compile.pass.cpp b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_input_iterator.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_input_iterator.compile.pass.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-concepts + +// template<class I> +// concept __nothrow_input_iterator; + +#include <memory> + +#include "test_iterators.h" + +struct InputProxyIterator { + using value_type = int; + using difference_type = int; + InputProxyIterator& operator++(); + InputProxyIterator operator++(int); + + int operator*() const; +}; + +static_assert(std::ranges::__nothrow_input_iterator<cpp20_input_iterator<int*>>); +static_assert(!std::ranges::__nothrow_input_iterator<output_iterator<int*>>); +static_assert(std::input_iterator<InputProxyIterator>); +static_assert(!std::ranges::__nothrow_input_iterator<InputProxyIterator>); diff --git a/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_input_range.compile.pass.cpp b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_input_range.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_input_range.compile.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-concepts + +// template<class R> +// concept __nothrow_input_range; + +#include <memory> + +#include "test_iterators.h" +#include "test_range.h" + +// Has to be a template to work with `test_range`. +template <typename> +struct InputProxyIterator { + using value_type = int; + using difference_type = int; + InputProxyIterator& operator++(); + InputProxyIterator operator++(int); + + int operator*() const; +}; + +static_assert(std::ranges::__nothrow_input_range<test_range<cpp20_input_iterator>>); +static_assert(std::ranges::input_range<test_range<InputProxyIterator>>); +static_assert(!std::ranges::__nothrow_input_range<test_range<InputProxyIterator>>); diff --git a/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_sentinel_for.compile.pass.cpp b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_sentinel_for.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/algorithms/specialized.algorithms/special.mem.concepts/nothrow_sentinel_for.compile.pass.cpp @@ -0,0 +1,18 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: libcpp-no-concepts + +// template<class S, class I> +// concept __nothrow_sentinel_for; + +#include <memory> + +static_assert(std::ranges::__nothrow_sentinel_for<int*, int*>); +static_assert(!std::ranges::__nothrow_sentinel_for<int*, long*>);