This is the initial patch to implement ranges in libc++.
Implements parts of:
- P0896R4 One Ranges Proposal
- P1870 forwarding-range is too subtle
- LWG3379 in several library names is misleading
Reviewed By: ldionne, #libc, cjdb, zoecarver, Quuxplusone
Differential Revision: https://reviews.llvm.org/D90999
"`3374 <https://wg21.link/LWG3374>`__","P0653 + P1006 should have made the other ``std::to_address``\ overload ``constexpr``\ ","Prague","|Complete|","12.0"
"`3375 <https://wg21.link/LWG3375>`__","``decay``\ in ``viewable_range``\ should be ``remove_cvref``\ ","Prague","",""
"`3377 <https://wg21.link/LWG3377>`__","``elements_view::iterator``\ befriends a specialization of itself","Prague","",""
-"`3379 <https://wg21.link/LWG3379>`__","""``safe``\ "" in several library names is misleading","Prague","",""
+"`3379 <https://wg21.link/LWG3379>`__","""``safe``\ "" in several library names is misleading","Prague","|In Progress|",""
"`3380 <https://wg21.link/LWG3380>`__","``common_type``\ and comparison categories","Prague","",""
"`3381 <https://wg21.link/LWG3381>`__","``begin``\ and ``data``\ must agree for ``contiguous_range``\ ","Prague","",""
"`3382 <https://wg21.link/LWG3382>`__","NTTP for ``pair``\ and ``array``\ ","Prague","",""
"`P1862 <https://wg21.link/P1862>`__","LWG","Ranges adaptors for non-copyable iterators","Belfast","* *",""
"`P1865 <https://wg21.link/P1865>`__","LWG","Add max() to latch and barrier","Belfast","|Complete|","11.0"
"`P1869 <https://wg21.link/P1869>`__","LWG","Rename 'condition_variable_any' interruptible wait methods","Belfast","* *",""
-"`P1870 <https://wg21.link/P1870>`__","LWG","forwarding-range is too subtle","Belfast","* *",""
+"`P1870 <https://wg21.link/P1870>`__","LWG","forwarding-range is too subtle","Belfast","|In Progress|",""
"`P1871 <https://wg21.link/P1871>`__","LWG","Should concepts be enabled or disabled?","Belfast","* *",""
"`P1872 <https://wg21.link/P1872>`__","LWG","span should have size_type, not index_type","Belfast","|Complete|","10.0"
"`P1878 <https://wg21.link/P1878>`__","LWG","Constraining Readable Types","Belfast","* *",""
__mutex_base
__node_handle
__nullptr
+ __ranges/enable_borrowed_range.h
__split_buffer
__sso_allocator
__std_stream
ostream
queue
random
+ ranges
ratio
regex
scoped_allocator
--- /dev/null
+// -*- C++ -*-
+//===------------------ __ranges/enable_borrowed_range.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_ENABLE_BORROWED_RANGE_H
+#define _LIBCPP___RANGES_ENABLE_BORROWED_RANGE_H
+
+// These customization variables are used in <span> and <string_view>. The
+// separate header is used to avoid including the entire <ranges> header in
+// <span> and <string_view>.
+
+#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 && !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges
+{
+
+// [range.range], ranges
+
+template <class>
+inline constexpr bool enable_borrowed_range = false;
+
+} // namespace ranges
+
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_ENABLE_BORROWED_RANGE_H
export initializer_list
export *
}
+ module ranges {
+ header "ranges"
+ export *
+ }
module ratio {
header "ratio"
export *
--- /dev/null
+// -*- 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 <compare> // see [compare.syn]
+#include <initializer_list> // see [initializer.list.syn]
+#include <iterator> // see [iterator.synopsis]
+
+namespace std::ranges {
+ // [range.range], ranges
+ template<class T>
+ inline constexpr bool enable_borrowed_range = false;
+}
+
+*/
+
+#include <__config>
+#include <__ranges/enable_borrowed_range.h>
+#include <compare> // Required by the standard.
+#include <initializer_list> // Required by the standard.
+#include <iterator> // Required by the standard.
+#include <type_traits>
+#include <version>
+
+#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 && !defined(_LIBCPP_HAS_NO_RANGES)
+
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP_RANGES
template <class ElementType, size_t Extent = dynamic_extent>
class span;
+template<class ElementType, size_t Extent>
+ inline constexpr bool ranges::enable_borrowed_range<span<ElementType, Extent>> = true;
+
// [span.objectrep], views of object representation
template <class ElementType, size_t Extent>
span<const byte, ((Extent == dynamic_extent) ? dynamic_extent :
(sizeof(ElementType) * Extent))> as_writable_bytes(span<ElementType, Extent> s) noexcept;
-namespace std {
template <class ElementType, size_t Extent = dynamic_extent>
class span {
public:
*/
#include <__config>
+#include <__ranges/enable_borrowed_range.h>
#include <array> // for array
#include <cstddef> // for byte
#include <iterator> // for iterators
size_type __size;
};
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+template <class _Tp, size_t _Extent>
+inline constexpr bool ranges::enable_borrowed_range<span<_Tp, _Extent> > = true;
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
// as_bytes & as_writable_bytes
template <class _Tp, size_t _Extent>
_LIBCPP_INLINE_VISIBILITY
template<class charT, class traits = char_traits<charT>>
class basic_string_view;
+ template<class charT, class traits>
+ inline constexpr bool ranges::enable_borrowed_range<basic_string_view<charT, traits>> = true; // C++20
+
// 7.9, basic_string_view non-member comparison functions
template<class charT, class traits>
constexpr bool operator==(basic_string_view<charT, traits> x,
*/
#include <__config>
+#include <__ranges/enable_borrowed_range.h>
#include <__string>
#include <iosfwd>
#include <algorithm>
size_type __size;
};
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
+template <class _CharT, class _Traits>
+inline constexpr bool ranges::enable_borrowed_range<basic_string_view<_CharT, _Traits> > = true;
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
// [string.view.comparison]
// operator ==
#endif
#include <queue>
#include <random>
+#include <ranges>
#include <ratio>
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
# include <regex>
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// WARNING: This test was generated by generate_header_inclusion_tests.py
+// and should not be edited manually.
+//
+// clang-format off
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// <ranges>
+
+// Test that <ranges> includes all the other headers it's supposed to.
+
+#include <ranges>
+#include "test_macros.h"
+
+#if !defined(_LIBCPP_RANGES)
+ # error "<ranges> was expected to define _LIBCPP_RANGES"
+#endif
+#if TEST_STD_VER > 17 && !defined(_LIBCPP_COMPARE)
+ # error "<ranges> should include <compare> in C++20 and later"
+#endif
+#if TEST_STD_VER > 03 && !defined(_LIBCPP_INITIALIZER_LIST)
+ # error "<ranges> should include <initializer_list> in C++20 and later"
+#endif
+#if !defined(_LIBCPP_ITERATOR)
+ # error "<ranges> should include <iterator> in C++20 and later"
+#endif
TEST_MACROS();
#include <random>
TEST_MACROS();
+#include <ranges>
+TEST_MACROS();
#include <ratio>
TEST_MACROS();
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
#endif
#include <queue>
#include <random>
+#include <ranges>
#include <ratio>
#ifndef _LIBCPP_HAS_NO_LOCALIZATION
# include <regex>
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// <ranges>
+
+#include <ranges>
+
+#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; }
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <span>
+
+// template<class ElementType, size_t Extent>
+// inline constexpr bool ranges::enable_borrowed_range<
+// span<ElementType, Extent>> = true;
+
+#include <span>
+
+#include "test_macros.h"
+
+void test() {
+ static_assert(std::ranges::enable_borrowed_range<std::span<int, 0> >);
+ static_assert(std::ranges::enable_borrowed_range<std::span<int, 42> >);
+ static_assert(std::ranges::enable_borrowed_range<std::span<int, std::dynamic_extent> >);
+ static_assert(!std::ranges::enable_borrowed_range<std::span<int, 42>&>);
+ static_assert(!std::ranges::enable_borrowed_range<std::span<int, 42> const>);
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// WARNING: This test was generated by generate_feature_test_macro_components.py
+// and should not be edited manually.
+//
+// clang-format off
+
+// <ranges>
+
+// Test the feature test macros defined by <ranges>
+
+/* Constant Value
+ __cpp_lib_ranges 201811L [C++20]
+*/
+
+#include <ranges>
+#include "test_macros.h"
+
+#if TEST_STD_VER < 14
+
+# ifdef __cpp_lib_ranges
+# error "__cpp_lib_ranges should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 14
+
+# ifdef __cpp_lib_ranges
+# error "__cpp_lib_ranges should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 17
+
+# ifdef __cpp_lib_ranges
+# error "__cpp_lib_ranges should not be defined before c++20"
+# endif
+
+#elif TEST_STD_VER == 20
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_ranges
+# error "__cpp_lib_ranges should be defined in c++20"
+# endif
+# if __cpp_lib_ranges != 201811L
+# error "__cpp_lib_ranges should have the value 201811L in c++20"
+# endif
+# else // _LIBCPP_VERSION
+# ifdef __cpp_lib_ranges
+# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#elif TEST_STD_VER > 20
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_ranges
+# error "__cpp_lib_ranges should be defined in c++2b"
+# endif
+# if __cpp_lib_ranges != 201811L
+# error "__cpp_lib_ranges should have the value 201811L in c++2b"
+# endif
+# else // _LIBCPP_VERSION
+# ifdef __cpp_lib_ranges
+# error "__cpp_lib_ranges should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+#endif // TEST_STD_VER > 20
+
+int main(int, char**) { return 0; }
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <ranges>
+
+// template<class>
+// inline constexpr bool enable_borrowed_range = false;
+
+#include <ranges>
+#include <array>
+#include <deque>
+#include <forward_list>
+#include <list>
+#include <map>
+#include <queue>
+#include <set>
+#include <stack>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include "test_macros.h"
+
+struct S {};
+
+void test() {
+ using std::ranges::enable_borrowed_range;
+ static_assert(!enable_borrowed_range<char>);
+ static_assert(!enable_borrowed_range<int>);
+ static_assert(!enable_borrowed_range<double>);
+ static_assert(!enable_borrowed_range<S>);
+
+ // Sequence containers
+ static_assert(!enable_borrowed_range<std::array<int, 0> >);
+ static_assert(!enable_borrowed_range<std::array<int, 42> >);
+ static_assert(!enable_borrowed_range<std::deque<int> >);
+ static_assert(!enable_borrowed_range<std::forward_list<int> >);
+ static_assert(!enable_borrowed_range<std::list<int> >);
+ static_assert(!enable_borrowed_range<std::vector<int> >);
+
+ // Associative containers
+ static_assert(!enable_borrowed_range<std::set<int> >);
+ static_assert(!enable_borrowed_range<std::map<int, int> >);
+ static_assert(!enable_borrowed_range<std::multiset<int> >);
+ static_assert(!enable_borrowed_range<std::multimap<int, int> >);
+
+ // Unordered associative containers
+ static_assert(!enable_borrowed_range<std::unordered_set<int> >);
+ static_assert(!enable_borrowed_range<std::unordered_map<int, int> >);
+ static_assert(!enable_borrowed_range<std::unordered_multiset<int> >);
+ static_assert(!enable_borrowed_range<std::unordered_multimap<int, int> >);
+
+ // Container adaptors
+ static_assert(!enable_borrowed_range<std::stack<int> >);
+ static_assert(!enable_borrowed_range<std::queue<int> >);
+ static_assert(!enable_borrowed_range<std::priority_queue<int> >);
+
+ // Both std::span and std::string_view have their own test.
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <string_view>
+
+// template<class charT, class traits>
+// inline constexpr bool ranges::enable_borrowed_range<
+// basic_string_view<charT, traits>> = true;
+
+#include <string_view>
+
+#include "test_macros.h"
+
+void test() {
+ using std::ranges::enable_borrowed_range;
+ static_assert(enable_borrowed_range<std::basic_string_view<char> >);
+ static_assert(enable_borrowed_range<std::basic_string_view<wchar_t> >);
+ static_assert(enable_borrowed_range<std::basic_string_view<char8_t> >);
+}
"optional": ["compare"],
"queue": ["compare", "initializer_list"],
"random": ["initializer_list"],
- # TODO "ranges": ["compare", "initializer_list", "iterator"],
+ "ranges": ["compare", "initializer_list", "iterator"],
"regex": ["compare", "initializer_list"],
"set": ["compare", "initializer_list"],
"stack": ["compare", "initializer_list"],