Skip to content

Commit 7b58c0e

Browse files
fix test
1 parent 9c80f3c commit 7b58c0e

File tree

11 files changed

+450
-132
lines changed

11 files changed

+450
-132
lines changed

libcxx/include/__ranges/concat_view.h

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -74,29 +74,42 @@ template <class... _Tp>
7474
using __extract_last _LIBCPP_NODEBUG = __extract_last_impl<_Tp...>::type;
7575
# endif
7676

77-
template <class _Tp, class... _Tail>
78-
constexpr bool __derived_from_pack =
79-
__derived_from_pack<_Tp, __extract_last<_Tail...>> && __derived_from_pack<_Tail...>;
77+
template <bool _Const, class... _Tp>
78+
struct __all_but_first_model_sized_range;
8079

81-
template <class _Tp, class _IterCategory>
82-
constexpr bool __derived_from_pack<_Tp, _IterCategory> = derived_from<_Tp, _IterCategory>;
80+
template <bool _Const, class _Head, class... _Tail>
81+
struct __all_but_first_model_sized_range<_Const, _Head, _Tail...> {
82+
static constexpr bool value = (sized_range<__maybe_const<_Const, _Tail>> && ...);
83+
};
8384

84-
template <class _View, class... _Views>
85-
struct __last_view : __last_view<_Views...> {};
85+
template <bool _Const, class... _Views>
86+
concept __all_random_access = (random_access_range<__maybe_const<_Const, _Views>> && ...);
8687

87-
template <class _View>
88-
struct __last_view<_View> {
89-
using type _LIBCPP_NODEBUG = _View;
90-
};
88+
template <bool _Const, class... _Views>
89+
concept __all_bidirectional = (bidirectional_range<__maybe_const<_Const, _Views>> && ...);
9190

92-
template <bool _Const, class... _Tp>
93-
struct __apply_drop_first;
91+
template <bool _Const, class... _Views>
92+
concept __all_forward = (forward_range<__maybe_const<_Const, _Views>> && ...);
9493

95-
template <bool _Const, class _Head, class... _Tail>
96-
struct __apply_drop_first<_Const, _Head, _Tail...> {
97-
static constexpr bool value = (sized_range<__maybe_const<_Const, _Tail>> && ...);
94+
template <bool _Const, class _First, class... _Tail>
95+
struct __all_common_ignore_last {
96+
static constexpr bool value =
97+
common_range<__maybe_const<_Const, _First>> && __all_common_ignore_last<_Const, _Tail...>::value;
98+
};
99+
100+
template <bool _Const, class _Tail>
101+
struct __all_common_ignore_last<_Const, _Tail> {
102+
static constexpr bool value = true;
98103
};
99104

105+
template <bool _Const, class... _Rs>
106+
concept __concat_is_random_access =
107+
(__all_random_access<_Const, _Rs...>) && (__all_common_ignore_last<_Const, _Rs...>::value);
108+
109+
template <bool _Const, class... _Rs>
110+
concept __concat_is_bidirectional =
111+
(__all_bidirectional<_Const, _Rs...>) && (__all_common_ignore_last<_Const, _Rs...>::value);
112+
100113
template <input_range... _Views>
101114
requires(view<_Views> && ...) && (sizeof...(_Views) > 0) && __concatable<_Views...>
102115
class concat_view : public view_interface<concat_view<_Views...>> {
@@ -129,7 +142,7 @@ class concat_view : public view_interface<concat_view<_Views...>> {
129142
_LIBCPP_HIDE_FROM_ABI constexpr auto end()
130143
requires(!(__simple_view<_Views> && ...))
131144
{
132-
if constexpr (common_range<__maybe_const<false, typename __last_view<_Views...>::type>>) {
145+
if constexpr (common_range<__maybe_const<false, __extract_last<_Views...>>>) {
133146
constexpr auto __n = sizeof...(_Views);
134147
return __iterator<false>(this, in_place_index<__n - 1>, ranges::end(std::get<__n - 1>(__views_)));
135148
} else {
@@ -140,7 +153,7 @@ class concat_view : public view_interface<concat_view<_Views...>> {
140153
_LIBCPP_HIDE_FROM_ABI constexpr auto end() const
141154
requires(range<const _Views> && ...)
142155
{
143-
if constexpr (common_range<__maybe_const<true, typename __last_view<_Views...>::type>>) {
156+
if constexpr (common_range<__maybe_const<true, __extract_last<_Views...>>>) {
144157
constexpr auto __n = sizeof...(_Views);
145158
return __iterator<true>(this, in_place_index<__n - 1>, ranges::end(std::get<__n - 1>(__views_)));
146159
} else {
@@ -176,14 +189,14 @@ template <bool _Const, typename... _Views>
176189
struct __concat_view_iterator_category<_Const, _Views...> {
177190
private:
178191
constexpr static bool __derive_pack_random_iterator =
179-
__derived_from_pack<typename iterator_traits<iterator_t<__maybe_const<_Const, _Views>>>::iterator_category...,
180-
random_access_iterator_tag>;
192+
(derived_from<typename iterator_traits<iterator_t<__maybe_const<_Const, _Views>>>::iterator_category,
193+
random_access_iterator_tag> && ...);
181194
constexpr static bool __derive_pack_bidirectional_iterator =
182-
__derived_from_pack<typename iterator_traits<iterator_t<__maybe_const<_Const, _Views>>>::iterator_category...,
183-
bidirectional_iterator_tag>;
195+
(derived_from<typename iterator_traits<iterator_t<__maybe_const<_Const, _Views>>>::iterator_category,
196+
bidirectional_iterator_tag> && ...);
184197
constexpr static bool __derive_pack_forward_iterator =
185-
__derived_from_pack<typename iterator_traits< iterator_t<__maybe_const<_Const, _Views>>>::iterator_category...,
186-
forward_iterator_tag>;
198+
(derived_from<typename iterator_traits< iterator_t<__maybe_const<_Const, _Views>>>::iterator_category,
199+
forward_iterator_tag> && ...);
187200

188201
public:
189202
using iterator_category =
@@ -573,7 +586,7 @@ class concat_view<_Views...>::__iterator : public __concat_view_iterator_categor
573586
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, default_sentinel_t)
574587
requires(sized_sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_Const, _Views>>> &&
575588
...) &&
576-
(__apply_drop_first<_Const, _Views...>::value)
589+
(__all_but_first_model_sized_range<_Const, _Views...>::value)
577590
{
578591
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
579592
!__x.__it_.valueless_by_exception(),
@@ -595,7 +608,7 @@ class concat_view<_Views...>::__iterator : public __concat_view_iterator_categor
595608
_LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(default_sentinel_t, const __iterator& __x)
596609
requires(sized_sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_Const, _Views>>> &&
597610
...) &&
598-
(__apply_drop_first<_Const, _Views...>::value)
611+
(__all_but_first_model_sized_range<_Const, _Views...>::value)
599612
{
600613
return -(__x - default_sentinel);
601614
}

libcxx/include/__ranges/concepts.h

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -172,33 +172,7 @@ concept __concatable = requires {
172172
typename __concat_rvalue_reference_t<_Rs...>;
173173
} && __concat_indirectly_readable<_Rs...>;
174174

175-
template <bool _Const, class... _Views>
176-
concept __all_random_access = (random_access_range<__maybe_const<_Const, _Views>> && ...);
177175

178-
template <bool _Const, class... _Views>
179-
concept __all_bidirectional = (bidirectional_range<__maybe_const<_Const, _Views>> && ...);
180-
181-
template <bool _Const, class... _Views>
182-
concept __all_forward = (forward_range<__maybe_const<_Const, _Views>> && ...);
183-
184-
template <bool _Const, class _First, class... _Tail>
185-
struct __all_common_ignore_last {
186-
static constexpr bool value =
187-
common_range<__maybe_const<_Const, _First>> && __all_common_ignore_last<_Const, _Tail...>::value;
188-
};
189-
190-
template <bool _Const, class _Tail>
191-
struct __all_common_ignore_last<_Const, _Tail> {
192-
static constexpr bool value = true;
193-
};
194-
195-
template <bool _Const, class... _Rs>
196-
concept __concat_is_random_access =
197-
(__all_random_access<_Const, _Rs...>) && (__all_common_ignore_last<_Const, _Rs...>::value);
198-
199-
template <bool _Const, class... _Rs>
200-
concept __concat_is_bidirectional =
201-
(__all_bidirectional<_Const, _Rs...>) && (__all_common_ignore_last<_Const, _Rs...>::value);
202176

203177
# endif // _LIBCPP_STD_VER >= 23
204178

libcxx/test/std/ranges/range.adaptors/range.concat/begin.pass.cpp

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,81 @@
1313

1414
#include <cassert>
1515
#include "test_iterators.h"
16+
#include "types.h"
1617

17-
constexpr void general_tests() {
18-
std::vector<int> v1 = {1, 2, 3, 4, 5, 6, 7, 8};
19-
std::vector<int> v2 = {1, 2, 3, 4, 5, 6, 7, 8};
20-
// Check the return type of `.begin()`
18+
template <class T>
19+
concept HasConstBegin = requires(const T& ct) { ct.begin(); };
20+
21+
template <class T>
22+
concept HasBegin = requires(T& t) { t.begin(); };
23+
24+
template <class T>
25+
concept HasConstAndNonConstBegin =
26+
HasConstBegin<T> &&
27+
requires(T& t, const T& ct) { requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>; };
28+
29+
template <class T>
30+
concept HasOnlyNonConstBegin = HasBegin<T> && !
31+
HasConstBegin<T>;
32+
33+
template <class T>
34+
concept HasOnlyConstBegin = HasConstBegin<T> && !
35+
HasConstAndNonConstBegin<T>;
36+
37+
constexpr void tests() {
38+
39+
// check the case of simple view
40+
{
41+
int buffer[4] = {1, 2, 3, 4};
42+
std::ranges::concat_view v(SimpleCommon{buffer}, SimpleCommon{buffer});
43+
static_assert(std::is_same_v<decltype(v.begin()), decltype(std::as_const(v).begin())>);
44+
assert(v.begin() == std::as_const(v).begin());
45+
46+
using View = decltype(v);
47+
static_assert(HasOnlyConstBegin<View>);
48+
static_assert(!HasOnlyNonConstBegin<View>);
49+
static_assert(!HasConstAndNonConstBegin<View>);
50+
}
51+
52+
// not all underlying ranges model simple view
2153
{
54+
int buffer[4] = {1, 2, 3, 4};
55+
std::ranges::concat_view v(SimpleCommon{buffer}, NonSimpleNonCommon{buffer});
56+
static_assert(!std::is_same_v<decltype(v.begin()), decltype(std::as_const(v).begin())>);
57+
assert(v.begin() == std::as_const(v).begin());
58+
59+
using View = decltype(v);
60+
static_assert(!HasOnlyConstBegin<View>);
61+
static_assert(!HasOnlyNonConstBegin<View>);
62+
static_assert(HasConstAndNonConstBegin<View>);
63+
}
64+
65+
// first view is empty
66+
{
67+
std::vector<int> v1;
68+
std::vector<int> v2 = {1, 2, 3, 4};
2269
std::ranges::concat_view view(v1, v2);
23-
using ConcatIterator = std::ranges::iterator_t<decltype(view)>;
24-
ASSERT_SAME_TYPE(ConcatIterator, decltype(view.begin()));
70+
auto it = view.begin();
71+
assert(*it == 1);
72+
assert(it + 4 == view.end());
2573
}
74+
75+
// first few views is empty
76+
{
77+
std::vector<int> v1;
78+
std::vector<int> v2;
79+
std::vector<int> v3 = {1, 2, 3, 4};
80+
std::ranges::concat_view view(v1, v2, v3);
81+
auto it = view.begin();
82+
assert(*it == 1);
83+
assert(it + 4 == view.end());
84+
}
85+
86+
2687
}
2788

2889
constexpr bool test() {
29-
general_tests();
90+
tests();
3091
return true;
3192
}
3293

File renamed without changes.

libcxx/test/std/ranges/range.adaptors/range.concat/ctad.pass.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ constexpr bool test() {
4343
static_assert(std::is_same_v<decltype(view), std::ranges::concat_view<std::ranges::ref_view<Range>>>);
4444
}
4545

46+
// Test a view which has a range and a view
47+
{
48+
Range r;
49+
View v;
50+
std::ranges::concat_view view(r, v);
51+
static_assert(std::is_same_v<decltype(view), std::ranges::concat_view<std::ranges::ref_view<Range>, View>>);
52+
}
53+
4654
return true;
4755
}
4856

libcxx/test/std/ranges/range.adaptors/range.concat/ctor.default.pass.cpp

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,17 @@ struct NoexceptView : std::ranges::view_base {
3939
int const* end() const;
4040
};
4141

42-
constexpr bool test() {
42+
struct HelperView : std::ranges::view_base {
43+
constexpr HelperView(const int* begin, const int *end) : begin_(begin), end_(end) {}
44+
constexpr int const* begin() const { return begin_; }
45+
constexpr int const* end() const { return end_; }
46+
47+
private:
48+
int const* begin_;
49+
int const* end_;
50+
};
51+
52+
constexpr void test_with_one_view() {
4353
{
4454
using View = std::ranges::concat_view<DefaultConstructibleView>;
4555
View view;
@@ -51,6 +61,30 @@ constexpr bool test() {
5161
assert(*it++ == 4);
5262
assert(it == end);
5363
}
64+
}
65+
66+
constexpr void test_with_more_than_one_view() {
67+
{
68+
using View = std::ranges::concat_view<HelperView, HelperView>;
69+
int arr1[] = {1,2};
70+
int arr2[] = {3,4};
71+
HelperView range1(arr1, arr1 + 2);
72+
HelperView range2(arr2, arr2 + 2);
73+
View view(range1, range2);
74+
auto it = view.begin();
75+
auto end = view.end();
76+
assert(*it++ == 1);
77+
assert(*it++ == 2);
78+
assert(*it++ == 3);
79+
assert(*it++ == 4);
80+
assert(it == end);
81+
}
82+
}
83+
84+
constexpr bool tests()
85+
{
86+
test_with_one_view();
87+
test_with_more_than_one_view();
5488

5589
// Check cases where the default constructor isn't provided
5690
{
@@ -73,8 +107,8 @@ constexpr bool test() {
73107
}
74108

75109
int main(int, char**) {
76-
test();
77-
static_assert(test());
110+
tests();
111+
static_assert(tests());
78112

79113
return 0;
80114
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: std-at-least-c++26
10+
11+
#include <cassert>
12+
#include <ranges>
13+
#include <vector>
14+
#include "test_macros.h"
15+
16+
int main(int, char**) {
17+
std::vector<int> v{1, 2, 3};
18+
auto r = std::views::counted(std::back_inserter(v), 3);
19+
auto c = std::views::concat(r);
20+
// expected-error@*:* {{}}
21+
22+
return 0;
23+
}

libcxx/test/std/ranges/range.adaptors/range.concat/ctor.view.pass.cpp

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,28 @@ struct Range : std::ranges::view_base {
2424
int* end_;
2525
};
2626

27-
struct TrackingRange : TrackInitialization, std::ranges::view_base {
28-
using TrackInitialization::TrackInitialization;
29-
int* begin() const;
30-
int* end() const;
27+
struct MoveAwareView : std::ranges::view_base {
28+
int moves = 0;
29+
constexpr MoveAwareView() = default;
30+
constexpr MoveAwareView(MoveAwareView&& other) : moves(other.moves + 1) { other.moves = 1; }
31+
constexpr MoveAwareView& operator=(MoveAwareView&& other) {
32+
moves = other.moves + 1;
33+
other.moves = 0;
34+
return *this;
35+
}
36+
constexpr const int* begin() const { return &moves; }
37+
constexpr const int* end() const { return &moves + 1; }
3138
};
3239

3340
constexpr bool test() {
34-
int buff[] = {1, 2, 3, 4};
41+
int buff[] = {1, 2};
42+
int buff2[] = {3, 4};
3543

36-
// Test explicit syntax
44+
// constructor from views
3745
{
38-
Range range(buff, buff + 4);
39-
std::ranges::concat_view<Range> view(range);
46+
Range range(buff, buff + 2);
47+
Range range2(buff2, buff2 + 2);
48+
std::ranges::concat_view view(range, range2);
4049
auto it = view.begin();
4150
auto end = view.end();
4251
assert(*it++ == 1);
@@ -48,11 +57,11 @@ constexpr bool test() {
4857

4958
// Make sure we move the view
5059
{
51-
bool moved = false, copied = false;
52-
TrackingRange range(&moved, &copied);
53-
[[maybe_unused]] std::ranges::concat_view<TrackingRange> view(std::move(range));
54-
assert(moved);
55-
assert(!copied);
60+
MoveAwareView mv;
61+
std::ranges::concat_view v{std::move(mv), MoveAwareView{}};
62+
auto it = v.begin();
63+
assert(*it++ == 2); // one move from the local variable to parameter, one move from parameter to member
64+
assert(*it++ == 1);
5665
}
5766

5867
return true;

0 commit comments

Comments
 (0)