diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -14,6 +14,7 @@ __mutex_base __node_handle __nullptr + __ranges_enable_helpers __split_buffer __sso_allocator __std_stream @@ -124,6 +125,7 @@ ostream queue random + ranges ratio regex scoped_allocator diff --git a/libcxx/include/__ranges_enable_helpers b/libcxx/include/__ranges_enable_helpers new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges_enable_helpers @@ -0,0 +1,63 @@ +// -*- C++ -*- +//===----------------------- __ranges_enable_helpers ----------------------===// +// +// 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_ENABLE_HELPERS +#define _LIBCPP___RANGES_ENABLE_HELPERS + +// These customization variables are used in and . The +// separate header is used to avoid including the entire header in +// and . + +/* + +namespace std::ranges { + // [range.range], ranges + template + inline constexpr bool enable_borrowed_range = false; + + // [range.view], views + template + inline constexpr bool enable_view = see below; + + struct view_base { }; +} + +*/ + +#include <__config> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +namespace ranges +{ + +// [range.range], ranges + +template +inline _LIBCPP_INLINE_VISIBILITY constexpr +bool enable_borrowed_range = false; + +} // namespace ranges + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP___RANGES_ENABLE_HELPERS diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -405,6 +405,11 @@ export initializer_list export * } + module ranges { + header "ranges" + export __ranges_enable_helpers + export * + } module ratio { header "ratio" export * @@ -529,6 +534,7 @@ module __hash_table { header "__hash_table" export * } module __locale { header "__locale" export * } module __mutex_base { header "__mutex_base" export * } + module __ranges_enable_helpers { header "__ranges_enable_helpers" export * } module __split_buffer { header "__split_buffer" export * } module __sso_allocator { header "__sso_allocator" export * } module __std_stream { header "__std_stream" export * } diff --git a/libcxx/include/ranges b/libcxx/include/ranges new file mode 100644 --- /dev/null +++ b/libcxx/include/ranges @@ -0,0 +1,336 @@ +// -*- C++ -*- +//===--------------------------- ranges -----------------------------------===// +// +// 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 +#define _LIBCPP_RANGES + +/* + +#include // see [compare.syn] +#include // see [initializer.list.syn] +#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; + inline constexpr unspecified rbegin = unspecified; + inline constexpr unspecified rend = unspecified; + inline constexpr unspecified crbegin = unspecified; + inline constexpr unspecified crend = unspecified; + + inline constexpr unspecified size = unspecified; + inline constexpr unspecified ssize = unspecified; + inline constexpr unspecified empty = unspecified; + inline constexpr unspecified data = unspecified; + inline constexpr unspecified cdata = unspecified; + } + + // [range.range], ranges + template + concept range = see below; + + template + inline constexpr bool enable_borrowed_range = false; + + template + concept borrowed_range = see below; + + template + using iterator_t = decltype(ranges::begin(declval())); + template + using sentinel_t = decltype(ranges::end(declval())); + template + using range_difference_t = iter_difference_t>; + template + using range_size_t = decltype(ranges::size(declval())); + template + using range_value_t = iter_value_t>; + template + using range_reference_t = iter_reference_t>; + template + using range_rvalue_reference_t = iter_rvalue_reference_t>; + + // [range.sized], sized ranges + template + inline constexpr bool disable_sized_range = false; + + template + concept sized_range = see below; + + // [range.view], views + template + inline constexpr bool enable_view = see below; + + struct view_base { }; + + template + concept view = see below; + + // [range.refinements], other range refinements + template + concept output_range = see below; + + template + concept input_range = see below; + + template + concept forward_range = see below; + + template + concept bidirectional_range = see below; + + template + concept random_access_range = see below; + + template + concept contiguous_range = see below; + + template + concept common_range = see below; + + template + concept viewable_range = see below; + + // [view.interface], class template view_interface + template + requires is_class_v && same_as> + class view_interface; + + // [range.subrange], sub-ranges + enum class subrange_kind : bool { unsized, sized }; + + template S = I, subrange_kind K = see below> + requires (K == subrange_kind::sized || !sized_sentinel_for) + class subrange; + + template S, subrange_kind K> + inline constexpr bool enable_borrowed_range> = true; + + // [range.dangling], dangling iterator handling + struct dangling; + + template + using borrowed_iterator_t = conditional_t, iterator_t, dangling>; + + template + using borrowed_subrange_t = + conditional_t, subrange>, dangling>; + + // [range.empty], empty view + template + requires is_object_v + class empty_view; + + template + inline constexpr bool enable_borrowed_range> = true; + + namespace views { + template + inline constexpr empty_view empty{}; + } + + // [range.single], single view + template + requires is_object_v + class single_view; + + namespace views { inline constexpr unspecified single = unspecified; } + + // [range.iota], iota view + template + requires weakly-equality-comparable-with && semiregular + class iota_view; + + template + inline constexpr bool enable_borrowed_range> = true; + + namespace views { inline constexpr unspecified iota = unspecified; } + + // [range.istream], istream view + template> + requires see below + class basic_istream_view; + template + basic_istream_view istream_view(basic_istream& s); + + // [range.all], all view + namespace views { + inline constexpr unspecified all = unspecified; + + template + using all_t = decltype(all(declval())); + } + + template + requires is_object_v + class ref_view; + + template + inline constexpr bool enable_borrowed_range> = true; + + // [range.filter], filter view + template> Pred> + requires view && is_object_v + class filter_view; + + namespace views { inline constexpr unspecified filter = unspecified; } + + // [range.transform], transform view + template + requires view && is_object_v && + regular_invocable> && + can-reference>> + class transform_view; + + namespace views { inline constexpr unspecified transform = unspecified; } + + // [range.take], take view + template class take_view; + + namespace views { inline constexpr unspecified take = unspecified; } + + // [range.take.while], take while view + template + requires input_range && is_object_v && + indirect_unary_predicate> + class take_while_view; + + namespace views { inline constexpr unspecified take_while = unspecified; } + + // [range.drop], drop view + template + class drop_view; + + namespace views { inline constexpr unspecified drop = unspecified; } + + // [range.drop.while], drop while view + template + requires input_range && is_object_v && + indirect_unary_predicate> + class drop_while_view; + + namespace views { inline constexpr unspecified drop_while = unspecified; } + + // [range.join], join view + template + requires view && input_range> && + (is_reference_v> || + view>) + class join_view; + + namespace views { inline constexpr unspecified join = unspecified; } + + // [range.split], split view + template + concept tiny-range = see below; // exposition only + + template + requires view && view && + indirectly_comparable, iterator_t, ranges::equal_to> && + (forward_range || tiny-range) + class split_view; + + namespace views { inline constexpr unspecified split = unspecified; } + + // [range.counted], counted view + namespace views { inline constexpr unspecified counted = unspecified; } + + // [range.common], common view + template + requires (!common_range && copyable>) + class common_view; + + namespace views { inline constexpr unspecified common = unspecified; } + + // [range.reverse], reverse view + template + requires bidirectional_range + class reverse_view; + + namespace views { inline constexpr unspecified reverse = unspecified; } + + // [range.elements], elements view + template + requires see below + class elements_view; + + template + using keys_view = elements_view, 0>; + template + using values_view = elements_view, 1>; + + namespace views { + template + inline constexpr unspecified elements = unspecified ; + inline constexpr auto keys = elements<0>; + inline constexpr auto values = elements<1>; + } +} + +namespace std { + namespace views = ranges::views; + + template + struct tuple_size> + : integral_constant {}; + template + struct tuple_element<0, ranges::subrange> { + using type = I; + }; + template + struct tuple_element<1, ranges::subrange> { + using type = S; + }; + template + struct tuple_element<0, const ranges::subrange> { + using type = I; + }; + template + struct tuple_element<1, const ranges::subrange> { + using type = S; + }; +} + +*/ + +#include <__config> +#include <__ranges_enable_helpers> +#include // Required by the standard. +#include // Required by the standard. +#include // Required by the standard. +#include +#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 _LIBCPP_STD_VER > 17 + +namespace ranges +{ + +} // namespace ranges + +#endif //_LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +_LIBCPP_POP_MACROS + +#endif // _LIBCPP_RANGES diff --git a/libcxx/include/span b/libcxx/include/span --- a/libcxx/include/span +++ b/libcxx/include/span @@ -22,6 +22,12 @@ template class span; +template + inline constexpr bool ranges::enable_view> = + Extent == 0 || Extent == dynamic_extent; +template + inline constexpr bool ranges::enable_borrowed_range> = true; + // [span.objectrep], views of object representation template span as_writable_bytes(span s) noexcept; -namespace std { template class span { public: @@ -123,6 +128,7 @@ */ #include <__config> +#include <__ranges_enable_helpers> #include // for array #include // for byte #include // for iterators @@ -513,6 +519,10 @@ size_type __size; }; +template +inline _LIBCPP_INLINE_VISIBILITY constexpr +bool _VSTD::ranges::enable_borrowed_range> = true; + // as_bytes & as_writable_bytes template _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/include/string_view b/libcxx/include/string_view --- a/libcxx/include/string_view +++ b/libcxx/include/string_view @@ -19,6 +19,11 @@ template> class basic_string_view; + template + inline constexpr bool ranges::enable_view> = true; // C++20 + template + inline constexpr bool ranges::enable_borrowed_range> = true; // C++20 + // 7.9, basic_string_view non-member comparison functions template constexpr bool operator==(basic_string_view x, @@ -172,6 +177,7 @@ */ #include <__config> +#include <__ranges_enable_helpers> #include <__string> #include #include @@ -608,6 +614,12 @@ size_type __size; }; +#if _LIBCPP_STD_VER > 17 +template +inline _LIBCPP_INLINE_VISIBILITY constexpr +bool _VSTD::ranges::enable_borrowed_range< + basic_string_view<_CharT, _Traits> > = true; +#endif // [string.view.comparison] // operator == diff --git a/libcxx/test/libcxx/double_include.sh.cpp b/libcxx/test/libcxx/double_include.sh.cpp --- a/libcxx/test/libcxx/double_include.sh.cpp +++ b/libcxx/test/libcxx/double_include.sh.cpp @@ -98,6 +98,7 @@ #include #include #include +#include #include #include #include diff --git a/libcxx/test/libcxx/min_max_macros.compile.pass.cpp b/libcxx/test/libcxx/min_max_macros.compile.pass.cpp --- a/libcxx/test/libcxx/min_max_macros.compile.pass.cpp +++ b/libcxx/test/libcxx/min_max_macros.compile.pass.cpp @@ -145,6 +145,8 @@ TEST_MACROS(); #include TEST_MACROS(); +#include +TEST_MACROS(); #include TEST_MACROS(); #include diff --git a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp --- a/libcxx/test/libcxx/no_assert_include.compile.pass.cpp +++ b/libcxx/test/libcxx/no_assert_include.compile.pass.cpp @@ -86,6 +86,7 @@ #include #include #include +#include #include #include #include diff --git a/libcxx/test/libcxx/ranges/version.compile.pass.cpp b/libcxx/test/libcxx/ranges/version.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/ranges/version.compile.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +#include + +#include "test_macros.h" + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +// Required for MSVC internal test runner compatibility. +int main(int, char**) +{ + return 0; +} diff --git a/libcxx/test/std/containers/views/enable_borrowed_range.compile.pass.cpp b/libcxx/test/std/containers/views/enable_borrowed_range.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/containers/views/enable_borrowed_range.compile.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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// + +// template +// inline constexpr bool ranges::enable_borrowed_range< +// span> = true; + +#include + +#include "test_macros.h" + +template +void test() +{ + using std::ranges::enable_borrowed_range; + using std::span; + using std::dynamic_extent; + + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); +} + +struct S{}; + +int main(int, char**) +{ + test(); + test(); + test(); + test(); + test(); + + return 0; +} diff --git a/libcxx/test/std/ranges/range.range/enable_borrowed_range.compile.pass.cpp b/libcxx/test/std/ranges/range.range/enable_borrowed_range.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/range.range/enable_borrowed_range.compile.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// inline constexpr bool enable_borrowed_range = false; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +struct S{}; + +int main(int, char**) +{ + using std::ranges::enable_borrowed_range; + static_assert(!enable_borrowed_range); + static_assert(!enable_borrowed_range); + static_assert(!enable_borrowed_range); + static_assert(!enable_borrowed_range); + + // Sequence containers + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + + // Associative containers + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + + // Unordered associative containers + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + + // Container adaptors + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + static_assert(!enable_borrowed_range>); + + // Both std::span and std::string_view have their own test. + + return 0; +} diff --git a/libcxx/test/std/strings/string.view/enable_borrowed_range.compile.pass.cpp b/libcxx/test/std/strings/string.view/enable_borrowed_range.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/strings/string.view/enable_borrowed_range.compile.pass.cpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// inline constexpr bool ranges::enable_borrowed_range< +// basic_string_view> = true; + +#include + +#include "test_macros.h" + +int main(int, char**) +{ + using std::ranges::enable_borrowed_range; + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + static_assert(enable_borrowed_range>); + + return 0; +} diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -118,7 +118,7 @@ P0608R3LWGA sane variant converting constructorSan DiegoComplete9.0 P0655R1LWGvisit<R>: Explicit Return Type for visitSan Diego P0771R1LWGstd::function move constructor should be noexceptSan DiegoComplete6.0 - P0896R4LWGThe One Ranges ProposalSan Diego + P0896R4LWGThe One Ranges ProposalSan DiegoIn progress P0899R1LWGP0899R1 - LWG 3016 is not a defectSan DiegoNothing to do P0919R3LWGHeterogeneous lookup for unordered containersSan DiegoComplete12.0 P0972R0LWG<chrono> zero(), min(), and max() should be noexceptSan DiegoComplete8.0 @@ -213,7 +213,7 @@ P1862LWGRanges adaptors for non-copyable iterators Belfast P1865LWGAdd max() to latch and barrier Belfast P1869LWGRename 'condition_variable_any' interruptible wait methods Belfast - P1870LWGforwarding-range is too subtle Belfast + P1870LWGforwarding-range is too subtle BelfastIn progress P1871LWGShould concepts be enabled or disabled? Belfast P1872LWGspan should have size_type, not index_type BelfastComplete10.0 P1878LWGConstraining Readable Types Belfast @@ -561,7 +561,7 @@ 3374P0653 + P1006 should have made the other std::to_address overload constexprPrague 3375decay in viewable_range should be remove_cvrefPrague 3377elements_view::iterator befriends a specialization of itselfPrague - 3379"safe" in several library names is misleadingPrague + 3379"safe" in several library names is misleadingPragueIn progress 3380common_type and comparison categoriesPrague 3381begin and data must agree for contiguous_rangePrague 3382NTTP for pair and arrayPrague