diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -35,6 +35,7 @@ __mutex_base __node_handle __nullptr + __ranges/access.h __ranges/enable_borrowed_range.h __split_buffer __sso_allocator @@ -150,6 +151,7 @@ random ranges ratio + ranges regex scoped_allocator semaphore diff --git a/libcxx/include/__ranges/access.h b/libcxx/include/__ranges/access.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges/access.h @@ -0,0 +1,217 @@ +// -*- C++ -*- +//===------------------------ __ranges/begin.h ----------------------------===// +// +// 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___RANGES_ACCESS_H +#define _LIBCPP___RANGES_ACCESS_H + +#include <__config> +#include <__iterator/concepts.h> +#include <__ranges/enable_borrowed_range.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_RANGES) + +// clang-format off + +namespace ranges { + template + concept __can_borrow = + is_lvalue_reference_v<_Tp> || enable_borrowed_range >; + + template + concept __is_complete = requires { sizeof(_Tp); }; +} // namespace ranges + +// [range.access.begin] +namespace ranges::__begin { + template + concept __member_begin = + __can_borrow<_Tp> && + requires(_Tp&& __t) { + { _VSTD::__decay_copy(__t.begin()) } -> input_or_output_iterator; + }; + + void begin(auto&) = delete; + void begin(const auto&) = delete; + + template + concept __unqualified_begin = + !__member_begin<_Tp> && + __can_borrow<_Tp> && + __class_or_enum > && + requires(_Tp && __t) { + { _VSTD::__decay_copy(begin(__t)) } -> input_or_output_iterator; + }; + + struct __fn { + template + [[nodiscard]] constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept { + constexpr bool __complete = __is_complete >; + if constexpr (__complete) { // used to disable cryptic diagnostic + return __t + 0; + } + else { + static_assert(__complete, "`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type."); + } + } + + template + requires __member_begin<_Tp> + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(_VSTD::__decay_copy(__t.begin()))) + { + return __t.begin(); + } + + template + requires __unqualified_begin<_Tp> + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(_VSTD::__decay_copy(begin(__t)))) + { + return begin(__t); + } + + void operator()(auto&&) const = delete; + }; +} // namespace ranges::__begin + +namespace ranges { + inline namespace __cpo { + inline constexpr auto begin = __begin::__fn{}; + } // namespace __cpo + + template + using iterator_t = decltype(ranges::begin(declval<_Tp&>())); +} // namespace ranges + +// [range.access.end] +namespace ranges::__end { + template + concept __member_end = + __can_borrow<_Tp> && + requires(_Tp&& __t) { + typename iterator_t<_Tp>; + { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for >; + }; + + void end(auto&) = delete; + void end(const auto&) = delete; + + template + concept __unqualified_end = + !__member_end<_Tp> && + __can_borrow<_Tp> && + __class_or_enum > && + requires(_Tp && __t) { + typename iterator_t<_Tp>; + { _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for >; + }; + + class __fn { + public: + template + [[nodiscard]] constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept { + constexpr bool __complete = __is_complete >; + if constexpr (__complete) { // used to disable cryptic diagnostic + return __t + _Np; + } + else { + static_assert(__complete, "`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type."); + } + } + + template + requires __member_end<_Tp> + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(_VSTD::__decay_copy(__t.end()))) + { + return _VSTD::forward<_Tp>(__t).end(); + } + + template + requires __unqualified_end<_Tp> + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(_VSTD::__decay_copy(end(__t)))) + { + return end(__t); + } + + void operator()(auto&&) const = delete; + }; +} // namespace ranges::__end + +namespace ranges::inline __cpo { + inline constexpr auto end = __end::__fn{}; +} // namespace ranges::__cpo + +namespace ranges::__cbegin { + struct __fn { + template + requires invocable + [[nodiscard]] constexpr auto operator()(_Tp& __t) const + noexcept(noexcept(ranges::begin(_VSTD::as_const(__t)))) + { + return ranges::begin(_VSTD::as_const(__t)); + } + + template + requires is_rvalue_reference_v<_Tp> && invocable + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(ranges::begin(static_cast<_Tp const&&>(__t)))) + { + return ranges::begin(static_cast<_Tp const&&>(__t)); + } + }; +} // namespace ranges::__cbegin + +namespace ranges::inline __cpo { + inline constexpr auto cbegin = __cbegin::__fn{}; +} // namespace ranges::__cpo + +namespace ranges::__cend { + struct __fn { + template + requires invocable + [[nodiscard]] constexpr auto operator()(_Tp& __t) const + noexcept(noexcept(ranges::end(_VSTD::as_const(__t)))) + { + return ranges::end(_VSTD::as_const(__t)); + } + + template + requires is_rvalue_reference_v<_Tp> && invocable + [[nodiscard]] constexpr auto operator()(_Tp&& __t) const + noexcept(noexcept(ranges::end(static_cast<_Tp const&&>(__t)))) + { + return ranges::end(static_cast<_Tp const&&>(__t)); + } + }; +} // namespace ranges::__cend + +namespace ranges::inline __cpo { + inline constexpr auto cend = __cend::__fn{}; +} // namespace ranges::__cpo + +// clang-format off + +#endif // !defined(_LIBCPP_HAS_NO_RANGES) + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_ACCESS_H diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -411,6 +411,9 @@ } module ranges { header "ranges" + export compare + export initializer_list + export iterator export * } module ratio { diff --git a/libcxx/include/ranges b/libcxx/include/ranges --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -17,14 +17,26 @@ #include // see [iterator.synopsis] namespace std::ranges { + inline namespace unspecified { + // [range.access], range access + inline constexpr unspecified begin = unspecified; + inline constexpr unspecified end = unspecified; + inline constexpr unspecified cbegin = unspecified; + inline constexpr unspecified cend = unspecified; + } + // [range.range], ranges template inline constexpr bool enable_borrowed_range = false; + + template + using iterator_t = decltype(ranges::begin(declval())); } */ #include <__config> +#include <__ranges/access.h> #include <__ranges/enable_borrowed_range.h> #include // Required by the standard. #include // Required by the standard. diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -2814,6 +2814,9 @@ inline _LIBCPP_INLINE_VISIBILITY typename decay<_Tp>::type __decay_copy(_Tp&& __t) +#if _LIBCPP_STD_VER > 17 +noexcept(is_nothrow_convertible_v<_Tp, remove_reference_t<_Tp>>) +#endif { return _VSTD::forward<_Tp>(__t); } diff --git a/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/associative/map/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// map + +#include + +#include +#include + +using range = std::map; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/associative/multimap/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// multimap + +#include + +#include +#include + +using range = std::multimap; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/associative/multiset/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// multiset + +#include + +#include +#include + +using range = std::multiset; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/associative/set/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// set + +#include + +#include +#include + +using range = std::set; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/array/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// array + +#include + +#include +#include + +using range = std::array; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/deque/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// deque + +#include + +#include +#include + +using range = std::deque; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/forwardlist/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// forward_list + +#include + +#include +#include + +using range = std::forward_list; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/list/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// list + +#include + +#include +#include + +using range = std::list; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector.bool/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// vector + +#include + +#include +#include + +using range = std::vector; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/sequences/vector/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// vector + +#include + +#include +#include + +using range = std::vector; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.map/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// unordered_map + +#include + +#include +#include + +using range = std::unordered_map; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.multimap/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// unordered_multimap + +#include + +#include +#include + +using range = std::unordered_multimap; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.multiset/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// unordered_multiset + +#include + +#include +#include + +using range = std::unordered_multiset; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/unord/unord.set/range_concept_conformance.compile.pass.cpp @@ -0,0 +1,25 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// unordered_multiset + +#include + +#include +#include + +using range = std::unordered_set; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); +static_assert(std::same_as, range::const_iterator>); diff --git a/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/containers/views/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/views/range_concept_conformance.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 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// span + +#include + +#include +#include + +using range = std::span; +namespace stdr = std::ranges; + +static_assert(std::same_as, range::iterator>); diff --git a/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/filesystems/class.directory_iterator/range_concept_conformance.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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// directory_iterator, recursive_directory_iterator + +#include "filesystem_include.h" + +#include +#include + +namespace stdr = std::ranges; + +static_assert(std::same_as, fs::directory_iterator>); +static_assert(std::same_as, fs::directory_iterator>); +static_assert(std::same_as, fs::recursive_directory_iterator>); +static_assert(std::same_as, fs::recursive_directory_iterator>); diff --git a/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp b/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/input.output/filesystems/class.path/range_concept_conformance.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 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// path + +#include "filesystem_include.h" + +#include +#include + +namespace stdr = std::ranges; + +static_assert(std::same_as, fs::path::iterator>); +static_assert(std::same_as, fs::path::const_iterator>); diff --git a/libcxx/test/std/ranges/range.access/begin.h b/libcxx/test/std/ranges/range.access/begin.h new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/begin.h @@ -0,0 +1,485 @@ +//===----------------------------------------------------------------------===// +// +// 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 LIBCXX_STD_TEST_RANGE_ACCESS_BEGIN_H +#define LIBCXX_STD_TEST_RANGE_ACCESS_BEGIN_H + +#include + +// clang-format off + +enum class enable_constness { mutable_only, const_only, both }; +enum called { neither, member, adl, both }; +constexpr bool borrowed = true; + +template +struct member_only { + constexpr int* begin() + requires (Const != enable_constness::const_only) { + callee |= called::member; + return &value; + } + + constexpr int const* begin() const + requires (Const != enable_constness::mutable_only) { + callee |= called::member; + return &value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct lvalue_member_only { + constexpr int* begin() & + requires (Const != enable_constness::const_only) { + callee |= called::member; + return &value; + } + + constexpr int const* begin() const& + requires (Const != enable_constness::mutable_only) { + callee |= called::member; + return &value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool +std::ranges::enable_borrowed_range > = true; + +template +struct rvalue_member_only { + constexpr int* begin() && + requires (Const != enable_constness::const_only) { + callee |= called::member; + return &value; + } + + constexpr int const* begin() const&& + requires (Const != enable_constness::mutable_only) { + callee |= called::member; + return &value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct member_preferred : member_only { + constexpr friend int* begin(member_preferred& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(member_preferred const& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct lvalue_member_preferred : lvalue_member_only { + constexpr friend int* begin(lvalue_member_preferred& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(lvalue_member_preferred const& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct rvalue_member_preferred : rvalue_member_only { + constexpr friend int* begin(rvalue_member_preferred&& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(rvalue_member_preferred const&& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct lvalue_adl_only { + constexpr friend int* begin(lvalue_adl_only& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(lvalue_adl_only const& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct rvalue_adl_only { + constexpr friend int* begin(rvalue_adl_only&& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(rvalue_adl_only const&& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct adl_only { + constexpr friend int* begin(adl_only& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(adl_only const& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int* begin(adl_only&& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(adl_only const&& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct lvalue_adl_with_private_members : private member_only { + constexpr friend int* begin(lvalue_adl_with_private_members& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(lvalue_adl_with_private_members const& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct lvalue_adl_with_private_lvalue_members : private lvalue_member_only { + constexpr friend int* begin(lvalue_adl_with_private_lvalue_members& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(lvalue_adl_with_private_lvalue_members const& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct lvalue_adl_with_private_rvalue_members : private rvalue_member_only { + constexpr friend int* begin(lvalue_adl_with_private_rvalue_members& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(lvalue_adl_with_private_rvalue_members const& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct rvalue_adl_with_private_members : private member_only { + constexpr friend int* begin(rvalue_adl_with_private_members&& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(rvalue_adl_with_private_members const&& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct rvalue_adl_with_private_lvalue_members : private lvalue_member_only { + constexpr friend int* begin(rvalue_adl_with_private_lvalue_members&& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(rvalue_adl_with_private_lvalue_members const&& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct rvalue_adl_with_private_rvalue_members : private rvalue_member_only { + constexpr friend int* begin(rvalue_adl_with_private_rvalue_members&& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(rvalue_adl_with_private_rvalue_members const&& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct lvalue_adl_with_bad_members { + constexpr int begin() { + callee |= called::member; + return value; + } + + constexpr int begin() const { + callee |= called::member; + return value; + } + + constexpr friend int* begin(lvalue_adl_with_bad_members& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(lvalue_adl_with_bad_members const& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = called::neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct rvalue_adl_with_bad_members { + constexpr int begin() { + callee |= called::member; + return value; + } + + constexpr int begin() const { + callee |= called::member; + return value; + } + + constexpr friend int* begin(rvalue_adl_with_bad_members&& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(rvalue_adl_with_bad_members const&& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + mutable int callee = called::neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct lvalue_adl_with_data_member_begin { + constexpr friend int* begin(lvalue_adl_with_data_member_begin& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(lvalue_adl_with_data_member_begin const& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + int begin = 0; + mutable int callee = called::neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +template +struct rvalue_adl_with_data_member_begin { + constexpr friend int* begin(rvalue_adl_with_data_member_begin&& x) + requires (Const != enable_constness::const_only) { + x.callee |= called::adl; + return &x.value; + } + + constexpr friend int const* begin(rvalue_adl_with_data_member_begin const&& x) + requires (Const != enable_constness::mutable_only) { + x.callee |= called::adl; + return &x.value; + } + + int value = 0; + int begin = 0; + mutable int callee = called::neither; +}; + +template +inline constexpr bool std::ranges::enable_borrowed_range > = true; + +struct empty {}; +template<> inline constexpr bool std::ranges::enable_borrowed_range = true; + +struct bad_member_return { + int begin(); + int begin() const; +}; + +template<> inline constexpr bool std::ranges::enable_borrowed_range = true; + +struct member_returns_decayable { + int*& begin(); + int*& begin() const; +}; + +struct adl_returns_decayable { + friend int*& begin(adl_returns_decayable&); + friend int*& begin(adl_returns_decayable const&); +}; + +template +struct nothrow_member_begin { + T begin() noexcept; + T begin() const noexcept; +}; + +template +struct nothrow_adl_begin { + friend T begin(nothrow_adl_begin&) noexcept; + friend T begin(nothrow_adl_begin const&) noexcept; +}; + +// clang-format on + +#endif // LIBCXX_STD_TEST_RANGE_ACCESS_BEGIN_H diff --git a/libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp b/libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.access/range.access.begin/begin.pass.cpp @@ -0,0 +1,337 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// UNSUPPORTED: gcc-10 +// XFAIL: msvc && clang + +// ranges::begin + +#include + +#include +#include +#include + +#include "../begin.h" + +#include "test_iterators.h" +#include "test_macros.h" + +using begin_t = decltype(std::ranges::begin); + +static_assert(std::semiregular >); +static_assert(std::invocable); +static_assert(!std::invocable); +static_assert(!std::invocable); +static_assert(!std::invocable); +ASSERT_NOEXCEPT(std::ranges::begin(std::declval())); + +// clang-format off +template +concept invocable_member_with_desired_result = + std::invocable && + requires(T&& t) { + { std::ranges::begin(std::forward(t)) } -> std::same_as >; + }; + +template +concept invocable_adl_with_desired_result = + std::invocable && + requires(T&& t) { + { std::ranges::begin(std::forward(t)) } -> std::same_as >; + }; +// clang-format on + +template