[libcxx-commits] [libcxx] [libc++][ranges] implement `ranges::elements_of` (PR #91414)
Xiaoyang Liu via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 8 11:04:38 PDT 2024
https://github.com/xiaoyang-sde updated https://github.com/llvm/llvm-project/pull/91414
>From 1807a424108f29e2cf73f8ac8b086a2f28f52939 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Tue, 7 May 2024 17:58:02 -0700
Subject: [PATCH 01/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__ranges/elements_of.h | 47 +++++++++++++++++++
libcxx/include/ranges | 5 ++
libcxx/modules/std/ranges.inc | 4 +-
.../range.elementsof/elements_of.pass.cpp | 39 +++++++++++++++
5 files changed, 95 insertions(+), 1 deletion(-)
create mode 100644 libcxx/include/__ranges/elements_of.h
create mode 100644 libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index fd7eb125e007b6..b1f9be1dc3d7da 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -646,6 +646,7 @@ set(files
__ranges/data.h
__ranges/drop_view.h
__ranges/drop_while_view.h
+ __ranges/elements_of.h
__ranges/elements_view.h
__ranges/empty.h
__ranges/empty_view.h
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
new file mode 100644
index 00000000000000..727ba92666eb36
--- /dev/null
+++ b/libcxx/include/__ranges/elements_of.h
@@ -0,0 +1,47 @@
+// -*- 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___RANGES_ELEMENTS_OF_H
+#define _LIBCPP___RANGES_ELEMENTS_OF_H
+
+#include <__config>
+#include <__memory/allocator.h>
+#include <__ranges/concepts.h>
+#include <cstddef>
+
+#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 >= 23
+
+namespace ranges {
+
+template <range _Range, class _Allocator = allocator<byte>>
+struct elements_of {
+ _LIBCPP_NO_UNIQUE_ADDRESS _Range range;
+ _LIBCPP_NO_UNIQUE_ADDRESS _Allocator allocator = _Allocator();
+};
+
+template <class _Range, class _Allocator = allocator<byte>>
+elements_of(_Range&&, _Allocator = _Allocator()) -> elements_of<_Range&&, _Allocator>;
+
+} // namespace ranges
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+#endif // _LIBCPP___RANGES_ELEMENTS_OF_H
diff --git a/libcxx/include/ranges b/libcxx/include/ranges
index 07a525ed8641fd..a8fbfc462bf0db 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -116,6 +116,10 @@ namespace std::ranges {
// [range.dangling], dangling iterator handling
struct dangling;
+ // [range.elementsof], class template elements_of
+ template<range R, class Allocator = allocator<byte>>
+ struct elements_of;
+
template<range R>
using borrowed_iterator_t = see below;
@@ -392,6 +396,7 @@ namespace std {
#include <__ranges/data.h>
#include <__ranges/drop_view.h>
#include <__ranges/drop_while_view.h>
+#include <__ranges/elements_of.h>
#include <__ranges/elements_view.h>
#include <__ranges/empty.h>
#include <__ranges/empty_view.h>
diff --git a/libcxx/modules/std/ranges.inc b/libcxx/modules/std/ranges.inc
index 80f31c79a1a405..94f3defdcbc356 100644
--- a/libcxx/modules/std/ranges.inc
+++ b/libcxx/modules/std/ranges.inc
@@ -83,8 +83,10 @@ export namespace std {
// [range.dangling], dangling iterator handling
using std::ranges::dangling;
+#if _LIBCPP_STD_VER >= 23
// [range.elementsof], class template elements_of
- // using std::ranges::elements_of;
+ using std::ranges::elements_of;
+#endif
using std::ranges::borrowed_iterator_t;
diff --git a/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp b/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
new file mode 100644
index 00000000000000..e1c2f91b960796
--- /dev/null
+++ b/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20
+
+// std::ranges::elements_of;
+
+#include <ranges>
+
+#include <vector>
+#include <concepts>
+
+constexpr bool test() {
+ {
+ auto elements_of = std::ranges::elements_of(std::vector<int>());
+ static_assert(
+ std::same_as<decltype(elements_of), std::ranges::elements_of<std::vector<int>&&, std::allocator<std::byte>>>);
+ static_assert(std::same_as<decltype(elements_of.range), std::vector<int>&&>);
+ static_assert(std::same_as<decltype(elements_of.allocator), std::allocator<std::byte>>);
+ }
+ {
+ auto elements_of = std::ranges::elements_of(std::vector<int>(), std::allocator<int>());
+ static_assert(
+ std::same_as<decltype(elements_of), std::ranges::elements_of<std::vector<int>&&, std::allocator<int>>>);
+ static_assert(std::same_as<decltype(elements_of.range), std::vector<int>&&>);
+ static_assert(std::same_as<decltype(elements_of.allocator), std::allocator<int>>);
+ }
+ return true;
+}
+
+int main() {
+ test();
+ static_assert(test());
+}
>From e14469bc4b829a7d40e8a445920d396ef08c5dda Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Tue, 7 May 2024 18:03:43 -0700
Subject: [PATCH 02/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/__ranges/elements_of.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
index 727ba92666eb36..d7cb1937563c60 100644
--- a/libcxx/include/__ranges/elements_of.h
+++ b/libcxx/include/__ranges/elements_of.h
@@ -44,4 +44,5 @@ elements_of(_Range&&, _Allocator = _Allocator()) -> elements_of<_Range&&, _Alloc
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS
+
#endif // _LIBCPP___RANGES_ELEMENTS_OF_H
>From 85ca069a211767c13059a315803fb71c442540a5 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Tue, 7 May 2024 18:04:53 -0700
Subject: [PATCH 03/13] [libc++][ranges] implement 'ranges::elements_of'
---
.../ranges/range.utility/range.elementsof/elements_of.pass.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp b/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
index e1c2f91b960796..378bcb0a2f13f3 100644
--- a/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
+++ b/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
@@ -12,8 +12,9 @@
#include <ranges>
-#include <vector>
#include <concepts>
+#include <memory>
+#include <vector>
constexpr bool test() {
{
>From b031c387baf12789a0da5268da2c92710087aac8 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Tue, 7 May 2024 19:45:10 -0700
Subject: [PATCH 04/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/module.modulemap | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 2974d12500c4cb..ee952c48c11d5b 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1699,6 +1699,7 @@ module std_private_ranges_dangling [system] { header "__ranges
module std_private_ranges_data [system] { header "__ranges/data.h" }
module std_private_ranges_drop_view [system] { header "__ranges/drop_view.h" }
module std_private_ranges_drop_while_view [system] { header "__ranges/drop_while_view.h" }
+module std_private_ranges_elements_of [system] { header "__ranges/elements_of.h" }
module std_private_ranges_elements_view [system] { header "__ranges/elements_view.h" }
module std_private_ranges_empty [system] { header "__ranges/empty.h" }
module std_private_ranges_empty_view [system] { header "__ranges/empty_view.h" }
>From 32b68f274244cc866d7edf5a83fffcb4ba0bec19 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Wed, 8 May 2024 13:22:10 -0400
Subject: [PATCH 05/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/__ranges/elements_of.h | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
index d7cb1937563c60..6219446a742a85 100644
--- a/libcxx/include/__ranges/elements_of.h
+++ b/libcxx/include/__ranges/elements_of.h
@@ -31,7 +31,11 @@ namespace ranges {
template <range _Range, class _Allocator = allocator<byte>>
struct elements_of {
_LIBCPP_NO_UNIQUE_ADDRESS _Range range;
- _LIBCPP_NO_UNIQUE_ADDRESS _Allocator allocator = _Allocator();
+ _LIBCPP_NO_UNIQUE_ADDRESS _Allocator allocator;
+
+ // This explicit constructor is required because AppleClang 15 hasn't implement P0960R3
+ explicit elements_of(_Range&& __range, _Allocator __allocator = _Allocator())
+ : range(std::move(__range)), allocator(std::move(__allocator)) {}
};
template <class _Range, class _Allocator = allocator<byte>>
>From 8e3560904d1cc79d014acba31eb2586edd71869d Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Wed, 8 May 2024 13:36:27 -0400
Subject: [PATCH 06/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/__ranges/elements_of.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
index 6219446a742a85..043bcb918a692d 100644
--- a/libcxx/include/__ranges/elements_of.h
+++ b/libcxx/include/__ranges/elements_of.h
@@ -13,6 +13,7 @@
#include <__config>
#include <__memory/allocator.h>
#include <__ranges/concepts.h>
+#include <__utility/move.h>
#include <cstddef>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
>From 162ce8ab091420ff39031aad4260843ac8df6391 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Wed, 8 May 2024 16:36:47 -0400
Subject: [PATCH 07/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/__ranges/elements_of.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
index 043bcb918a692d..93020c93d5f7b8 100644
--- a/libcxx/include/__ranges/elements_of.h
+++ b/libcxx/include/__ranges/elements_of.h
@@ -35,7 +35,7 @@ struct elements_of {
_LIBCPP_NO_UNIQUE_ADDRESS _Allocator allocator;
// This explicit constructor is required because AppleClang 15 hasn't implement P0960R3
- explicit elements_of(_Range&& __range, _Allocator __allocator = _Allocator())
+ _LIBCPP_HIDE_FROM_ABI explicit constexpr elements_of(_Range __range, _Allocator __allocator = _Allocator())
: range(std::move(__range)), allocator(std::move(__allocator)) {}
};
>From 9dd983d4ccd1ac0e1b5a74340212d6013309cf2d Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Wed, 8 May 2024 16:51:32 -0400
Subject: [PATCH 08/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/__ranges/elements_of.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
index 93020c93d5f7b8..edce0af345f378 100644
--- a/libcxx/include/__ranges/elements_of.h
+++ b/libcxx/include/__ranges/elements_of.h
@@ -35,8 +35,8 @@ struct elements_of {
_LIBCPP_NO_UNIQUE_ADDRESS _Allocator allocator;
// This explicit constructor is required because AppleClang 15 hasn't implement P0960R3
- _LIBCPP_HIDE_FROM_ABI explicit constexpr elements_of(_Range __range, _Allocator __allocator = _Allocator())
- : range(std::move(__range)), allocator(std::move(__allocator)) {}
+ _LIBCPP_HIDE_FROM_ABI explicit constexpr elements_of(_Range __range, _Allocator __alloc = _Allocator())
+ : range(std::move(__range)), allocator(std::move(__alloc)) {}
};
template <class _Range, class _Allocator = allocator<byte>>
>From 8291917ab08f32b609b7c2711ce63de9b649051b Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Tue, 14 May 2024 12:49:39 -0400
Subject: [PATCH 09/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/__ranges/elements_of.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
index edce0af345f378..f446d3c12d67e7 100644
--- a/libcxx/include/__ranges/elements_of.h
+++ b/libcxx/include/__ranges/elements_of.h
@@ -40,6 +40,8 @@ struct elements_of {
};
template <class _Range, class _Allocator = allocator<byte>>
+// This explicit constraint is required because AppleClang 15 might not deduce the correct type for `_Range` without it
+ requires range<_Range&&>
elements_of(_Range&&, _Allocator = _Allocator()) -> elements_of<_Range&&, _Allocator>;
} // namespace ranges
>From b741665949ed7fc8b58b757ae22499b7bff0aba7 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Sun, 28 Jul 2024 22:10:33 +0800
Subject: [PATCH 10/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/__ranges/elements_of.h | 6 ++-
.../range.elementsof/elements_of.pass.cpp | 48 +++++++++++++------
2 files changed, 38 insertions(+), 16 deletions(-)
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
index f446d3c12d67e7..1b8f916589505c 100644
--- a/libcxx/include/__ranges/elements_of.h
+++ b/libcxx/include/__ranges/elements_of.h
@@ -32,16 +32,20 @@ namespace ranges {
template <range _Range, class _Allocator = allocator<byte>>
struct elements_of {
_LIBCPP_NO_UNIQUE_ADDRESS _Range range;
- _LIBCPP_NO_UNIQUE_ADDRESS _Allocator allocator;
+ _LIBCPP_NO_UNIQUE_ADDRESS _Allocator allocator = _Allocator();
+# if defined(_LIBCPP_COMPILER_CLANG_BASED) && _LIBCPP_CLANG_VER < 1600
// This explicit constructor is required because AppleClang 15 hasn't implement P0960R3
_LIBCPP_HIDE_FROM_ABI explicit constexpr elements_of(_Range __range, _Allocator __alloc = _Allocator())
: range(std::move(__range)), allocator(std::move(__alloc)) {}
+# endif
};
template <class _Range, class _Allocator = allocator<byte>>
+# if defined(_LIBCPP_COMPILER_CLANG_BASED) && _LIBCPP_CLANG_VER < 1600
// This explicit constraint is required because AppleClang 15 might not deduce the correct type for `_Range` without it
requires range<_Range&&>
+# endif
elements_of(_Range&&, _Allocator = _Allocator()) -> elements_of<_Range&&, _Allocator>;
} // namespace ranges
diff --git a/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp b/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
index 378bcb0a2f13f3..8bdb4f7992ae23 100644
--- a/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
+++ b/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
@@ -16,25 +16,43 @@
#include <memory>
#include <vector>
+#include "min_allocator.h"
+#include "test_allocator.h"
+#include "test_iterators.h"
+
+template <typename Range>
+constexpr bool test_range() {
+ std::same_as<std::ranges::elements_of<Range&&, std::allocator<std::byte>>> decltype(auto) elements_of =
+ std::ranges::elements_of(Range());
+ [[maybe_unused]] std::same_as<Range&&> decltype(auto) elements_of_range = std::move(elements_of.range);
+ [[maybe_unused]] std::same_as<std::allocator<std::byte>> decltype(auto) elements_of_allocator = elements_of.allocator;
+ return true;
+}
+
+template <typename Range, typename Allocator>
+constexpr bool test_range_with_allocator() {
+ std::same_as< std::ranges::elements_of< Range&&, Allocator >> decltype(auto) elements_of =
+ std::ranges::elements_of(Range(), Allocator());
+ [[maybe_unused]] std::same_as<Range&&> decltype(auto) elements_of_range = std::move(elements_of.range);
+ [[maybe_unused]] std::same_as<Allocator> decltype(auto) elements_of_allocator = elements_of.allocator;
+ return true;
+}
+
constexpr bool test() {
- {
- auto elements_of = std::ranges::elements_of(std::vector<int>());
- static_assert(
- std::same_as<decltype(elements_of), std::ranges::elements_of<std::vector<int>&&, std::allocator<std::byte>>>);
- static_assert(std::same_as<decltype(elements_of.range), std::vector<int>&&>);
- static_assert(std::same_as<decltype(elements_of.allocator), std::allocator<std::byte>>);
- }
- {
- auto elements_of = std::ranges::elements_of(std::vector<int>(), std::allocator<int>());
- static_assert(
- std::same_as<decltype(elements_of), std::ranges::elements_of<std::vector<int>&&, std::allocator<int>>>);
- static_assert(std::same_as<decltype(elements_of.range), std::vector<int>&&>);
- static_assert(std::same_as<decltype(elements_of.allocator), std::allocator<int>>);
- }
+ types::for_each(types::type_list<std::allocator<std::byte>, min_allocator<std::byte>, test_allocator<std::byte>>{},
+ []<class Allocator> {
+ types::for_each(types::type_list<std::vector<int>>{}, []<class Range> {
+ test_range<Range>();
+ test_range_with_allocator<Range, Allocator>();
+ });
+ });
+
return true;
}
-int main() {
+int main(int, char**) {
test();
static_assert(test());
+
+ return 0;
}
>From 07a62fe1e65a3c5c147acc9088f26a36faffa57e Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Thu, 8 Aug 2024 12:50:36 -0400
Subject: [PATCH 11/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/__ranges/elements_of.h | 4 ++--
libcxx/test/libcxx/transitive_includes/cxx03.csv | 1 +
libcxx/test/libcxx/transitive_includes/cxx11.csv | 1 +
libcxx/test/libcxx/transitive_includes/cxx14.csv | 1 +
libcxx/test/libcxx/transitive_includes/cxx17.csv | 1 +
libcxx/test/libcxx/transitive_includes/cxx20.csv | 1 +
libcxx/test/libcxx/transitive_includes/cxx23.csv | 1 +
libcxx/test/libcxx/transitive_includes/cxx26.csv | 1 +
8 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
index 1b8f916589505c..b2a93e9d553409 100644
--- a/libcxx/include/__ranges/elements_of.h
+++ b/libcxx/include/__ranges/elements_of.h
@@ -35,7 +35,7 @@ struct elements_of {
_LIBCPP_NO_UNIQUE_ADDRESS _Allocator allocator = _Allocator();
# if defined(_LIBCPP_COMPILER_CLANG_BASED) && _LIBCPP_CLANG_VER < 1600
- // This explicit constructor is required because AppleClang 15 hasn't implement P0960R3
+ // This explicit constructor is required because AppleClang 15 hasn't implemented P0960R3.
_LIBCPP_HIDE_FROM_ABI explicit constexpr elements_of(_Range __range, _Allocator __alloc = _Allocator())
: range(std::move(__range)), allocator(std::move(__alloc)) {}
# endif
@@ -43,7 +43,7 @@ struct elements_of {
template <class _Range, class _Allocator = allocator<byte>>
# if defined(_LIBCPP_COMPILER_CLANG_BASED) && _LIBCPP_CLANG_VER < 1600
-// This explicit constraint is required because AppleClang 15 might not deduce the correct type for `_Range` without it
+// This explicit constraint is required because AppleClang 15 might not deduce the correct type for `_Range` without it.
requires range<_Range&&>
# endif
elements_of(_Range&&, _Allocator = _Allocator()) -> elements_of<_Range&&, _Allocator>;
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index fd2cd7f1c2d961..f0efe06a01cd18 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -671,6 +671,7 @@ ranges initializer_list
ranges iosfwd
ranges iterator
ranges limits
+ranges new
ranges optional
ranges span
ranges tuple
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index 04122fd0f4571a..64a4954730d979 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv
@@ -676,6 +676,7 @@ ranges initializer_list
ranges iosfwd
ranges iterator
ranges limits
+ranges new
ranges optional
ranges span
ranges tuple
diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 42c742bead0c1f..bc56918cb638b7 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv
@@ -679,6 +679,7 @@ ranges initializer_list
ranges iosfwd
ranges iterator
ranges limits
+ranges new
ranges optional
ranges span
ranges tuple
diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index bc0659127d4bf5..29791eb0b56e32 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv
@@ -680,6 +680,7 @@ ranges initializer_list
ranges iosfwd
ranges iterator
ranges limits
+ranges new
ranges optional
ranges span
ranges tuple
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index fed0944f0219c4..70470de2106e77 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -687,6 +687,7 @@ ranges initializer_list
ranges iosfwd
ranges iterator
ranges limits
+ranges new
ranges optional
ranges span
ranges tuple
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index 53f99384a7f573..117a87b66a2cdb 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -464,6 +464,7 @@ ranges cwchar
ranges initializer_list
ranges iterator
ranges limits
+ranges new
ranges optional
ranges span
ranges tuple
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index 53f99384a7f573..117a87b66a2cdb 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -464,6 +464,7 @@ ranges cwchar
ranges initializer_list
ranges iterator
ranges limits
+ranges new
ranges optional
ranges span
ranges tuple
>From 74bd1855a16977ffd2e93619fa0e0cdfe83762d3 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Thu, 8 Aug 2024 12:55:24 -0400
Subject: [PATCH 12/13] [libc++][ranges] implement 'ranges::elements_of'
---
libcxx/include/__ranges/elements_of.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libcxx/include/__ranges/elements_of.h b/libcxx/include/__ranges/elements_of.h
index b2a93e9d553409..f23e8dd4a15e5d 100644
--- a/libcxx/include/__ranges/elements_of.h
+++ b/libcxx/include/__ranges/elements_of.h
@@ -34,7 +34,7 @@ struct elements_of {
_LIBCPP_NO_UNIQUE_ADDRESS _Range range;
_LIBCPP_NO_UNIQUE_ADDRESS _Allocator allocator = _Allocator();
-# if defined(_LIBCPP_COMPILER_CLANG_BASED) && _LIBCPP_CLANG_VER < 1600
+# if defined(_LIBCPP_COMPILER_CLANG_BASED) && defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1600
// This explicit constructor is required because AppleClang 15 hasn't implemented P0960R3.
_LIBCPP_HIDE_FROM_ABI explicit constexpr elements_of(_Range __range, _Allocator __alloc = _Allocator())
: range(std::move(__range)), allocator(std::move(__alloc)) {}
@@ -42,7 +42,7 @@ struct elements_of {
};
template <class _Range, class _Allocator = allocator<byte>>
-# if defined(_LIBCPP_COMPILER_CLANG_BASED) && _LIBCPP_CLANG_VER < 1600
+# if defined(_LIBCPP_COMPILER_CLANG_BASED) && defined(_LIBCPP_APPLE_CLANG_VER) && _LIBCPP_APPLE_CLANG_VER < 1600
// This explicit constraint is required because AppleClang 15 might not deduce the correct type for `_Range` without it.
requires range<_Range&&>
# endif
>From 5e37e03d58d03a739942a0354646f057312be35f Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Thu, 8 Aug 2024 14:04:15 -0400
Subject: [PATCH 13/13] [libc++][ranges] implement 'ranges::elements_of'
---
.../range.elementsof/ctad.compile.pass.cpp | 49 ++++++++++++++
.../range.elementsof/elements_of.pass.cpp | 66 ++++++++++++++-----
2 files changed, 98 insertions(+), 17 deletions(-)
create mode 100644 libcxx/test/std/ranges/range.utility/range.elementsof/ctad.compile.pass.cpp
diff --git a/libcxx/test/std/ranges/range.utility/range.elementsof/ctad.compile.pass.cpp b/libcxx/test/std/ranges/range.utility/range.elementsof/ctad.compile.pass.cpp
new file mode 100644
index 00000000000000..3a679b521f75e5
--- /dev/null
+++ b/libcxx/test/std/ranges/range.utility/range.elementsof/ctad.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, c++20
+
+// std::ranges::elements_of;
+
+#include <ranges>
+
+#include <memory>
+
+#include "min_allocator.h"
+#include "test_allocator.h"
+#include "test_iterators.h"
+
+template <class Iterator>
+struct Range {
+ Iterator begin() const;
+ sentinel_wrapper<Iterator> end() const;
+};
+
+constexpr bool test() {
+ types::for_each(
+ types::type_list<std::allocator<std::byte>, min_allocator<std::byte>, test_allocator<std::byte>>{},
+ []<class Allocator> {
+ types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class Iterator> {
+ Range<Iterator> r;
+ static_assert(std::same_as<decltype(std::ranges::elements_of(r)),
+ std::ranges::elements_of<Range<Iterator>&, std::allocator<std::byte>>>);
+ static_assert(std::same_as<decltype(std::ranges::elements_of(Range<Iterator>())),
+ std::ranges::elements_of<Range<Iterator>&&, std::allocator<std::byte>>>);
+
+ Allocator a;
+ static_assert(std::same_as<decltype(std::ranges::elements_of(r, a)),
+ std::ranges::elements_of<Range<Iterator>&, Allocator>>);
+ static_assert(std::same_as<decltype(std::ranges::elements_of(Range<Iterator>(), Allocator())),
+ std::ranges::elements_of<Range<Iterator>&&, Allocator>>);
+ });
+ });
+
+ return true;
+}
+
+static_assert(test());
diff --git a/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp b/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
index 8bdb4f7992ae23..8c6a8f98058c85 100644
--- a/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
+++ b/libcxx/test/std/ranges/range.utility/range.elementsof/elements_of.pass.cpp
@@ -12,7 +12,6 @@
#include <ranges>
-#include <concepts>
#include <memory>
#include <vector>
@@ -20,30 +19,63 @@
#include "test_allocator.h"
#include "test_iterators.h"
-template <typename Range>
+template <class Iterator>
+struct Range {
+ using Sentinel = sentinel_wrapper<Iterator>;
+
+ Iterator begin() { return Iterator(data.data()); }
+
+ sentinel_wrapper<Iterator> end() { return Sentinel(Iterator(data.data() + data.size())); }
+
+ std::vector<int> data = {0, 1, 2, 3};
+};
+
+template <class Range, class Allocator>
constexpr bool test_range() {
- std::same_as<std::ranges::elements_of<Range&&, std::allocator<std::byte>>> decltype(auto) elements_of =
- std::ranges::elements_of(Range());
- [[maybe_unused]] std::same_as<Range&&> decltype(auto) elements_of_range = std::move(elements_of.range);
- [[maybe_unused]] std::same_as<std::allocator<std::byte>> decltype(auto) elements_of_allocator = elements_of.allocator;
- return true;
-}
+ Range r;
+
+ using elements_of_t = std::ranges::elements_of<Range&, Allocator>;
+ {
+ // constructor
+ std::same_as<elements_of_t> decltype(auto) elements_of = std::ranges::elements_of(r, Allocator());
+ [[maybe_unused]] std::same_as<Range&> decltype(auto) elements_of_range = elements_of.range;
+ [[maybe_unused]] std::same_as<Allocator> decltype(auto) elements_of_allocator = elements_of.allocator;
+ }
+ {
+ // designated initializer
+ std::same_as<elements_of_t> decltype(auto) elements_of = std::ranges::elements_of{
+ .range = r,
+ .allocator = Allocator(),
+ };
+ [[maybe_unused]] std::same_as<Range&> decltype(auto) elements_of_range = elements_of.range;
+ [[maybe_unused]] std::same_as<Allocator> decltype(auto) elements_of_allocator = elements_of.allocator;
+ }
+ {
+ // copy constructor
+ std::same_as<elements_of_t> decltype(auto) elements_of_1 = std::ranges::elements_of(r, Allocator());
+ std::same_as<elements_of_t> auto elements_of_2 = elements_of_1;
+ [[maybe_unused]] std::same_as<Range&> decltype(auto) elements_of_1_range = elements_of_1.range;
+ [[maybe_unused]] std::same_as<Range&> decltype(auto) elements_of_2_range = elements_of_2.range;
+ [[maybe_unused]] std::same_as<Allocator> decltype(auto) elements_of_2_allocator = elements_of_2.allocator;
+ }
-template <typename Range, typename Allocator>
-constexpr bool test_range_with_allocator() {
- std::same_as< std::ranges::elements_of< Range&&, Allocator >> decltype(auto) elements_of =
- std::ranges::elements_of(Range(), Allocator());
- [[maybe_unused]] std::same_as<Range&&> decltype(auto) elements_of_range = std::move(elements_of.range);
- [[maybe_unused]] std::same_as<Allocator> decltype(auto) elements_of_allocator = elements_of.allocator;
+ using elements_of_r_t = std::ranges::elements_of<Range&&, Allocator>;
+ {
+ // move constructor
+ std::same_as<elements_of_r_t> decltype(auto) elements_of_1 = std::ranges::elements_of(std::move(r), Allocator());
+ std::same_as<elements_of_r_t> auto elements_of_2 = std::move(elements_of_1);
+ [[maybe_unused]] std::same_as<Range&&> decltype(auto) elements_of_1_range = std::move(elements_of_1.range);
+ [[maybe_unused]] std::same_as<Range&&> decltype(auto) elements_of_2_range = std::move(elements_of_2.range);
+ [[maybe_unused]] std::same_as<Allocator> decltype(auto) elements_of_2_allocator = elements_of_2.allocator;
+ }
return true;
}
constexpr bool test() {
types::for_each(types::type_list<std::allocator<std::byte>, min_allocator<std::byte>, test_allocator<std::byte>>{},
[]<class Allocator> {
- types::for_each(types::type_list<std::vector<int>>{}, []<class Range> {
- test_range<Range>();
- test_range_with_allocator<Range, Allocator>();
+ types::for_each(types::cpp20_input_iterator_list<int*>{}, []<class Iterator> {
+ test_range<Range<Iterator>, Allocator>();
});
});
More information about the libcxx-commits
mailing list