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 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 // UNSUPPORTED: libcpp-no-concepts
11 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
12 
13 // std::views::common
14 
15 #include <ranges>
16 
17 #include <array>
18 #include <cassert>
19 #include <concepts>
20 #include <utility>
21 
22 #include "test_iterators.h"
23 #include "types.h"
24 
25 template <class View, class T>
26 concept CanBePiped = requires (View&& view, T&& t) {
27   { std::forward<View>(view) | std::forward<T>(t) };
28 };
29 
30 constexpr bool test() {
31   int buf[] = {1, 2, 3};
32 
33   // views::common(r) is equivalent to views::all(r) if r is a common_range
34   {
35     {
36       CommonView view(buf, buf + 3);
37       std::same_as<CommonView> auto result = std::views::common(view);
38       assert(result.begin_ == buf);
39       assert(result.end_ == buf + 3);
40     }
41     {
42       using NotAView = std::array<int, 3>;
43       NotAView arr = {1, 2, 3};
44       std::same_as<std::ranges::ref_view<NotAView>> auto result = std::views::common(arr);
45       assert(result.begin() == arr.begin());
46       assert(result.end() == arr.end());
47     }
48   }
49 
50   // Otherwise, views::common(r) is equivalent to ranges::common_view{r}
51   {
52     NonCommonView view(buf, buf + 3);
53     std::same_as<std::ranges::common_view<NonCommonView>> auto result = std::views::common(view);
54     assert(result.base().begin_ == buf);
55     assert(result.base().end_ == buf + 3);
56   }
57 
58   // Test that std::views::common is a range adaptor
59   {
60     using SomeView = NonCommonView;
61 
62     // Test `v | views::common`
63     {
64       SomeView view(buf, buf + 3);
65       std::same_as<std::ranges::common_view<SomeView>> auto result = view | std::views::common;
66       assert(result.base().begin_ == buf);
67       assert(result.base().end_ == buf + 3);
68     }
69 
70     // Test `adaptor | views::common`
71     {
72       SomeView view(buf, buf + 3);
73       auto f = [](int i) { return i; };
74       auto const partial = std::views::transform(f) | std::views::common;
75       using Result = std::ranges::common_view<std::ranges::transform_view<SomeView, decltype(f)>>;
76       std::same_as<Result> auto result = partial(view);
77       assert(result.base().base().begin_ == buf);
78       assert(result.base().base().end_ == buf + 3);
79     }
80 
81     // Test `views::common | adaptor`
82     {
83       SomeView view(buf, buf + 3);
84       auto f = [](int i) { return i; };
85       auto const partial = std::views::common | std::views::transform(f);
86       using Result = std::ranges::transform_view<std::ranges::common_view<SomeView>, decltype(f)>;
87       std::same_as<Result> auto result = partial(view);
88       assert(result.base().base().begin_ == buf);
89       assert(result.base().base().end_ == buf + 3);
90     }
91 
92     // Check SFINAE friendliness
93     {
94       struct NotAView { };
95       static_assert(!std::is_invocable_v<decltype(std::views::common)>);
96       static_assert(!std::is_invocable_v<decltype(std::views::common), NotAView>);
97       static_assert( CanBePiped<SomeView&,   decltype(std::views::common)>);
98       static_assert( CanBePiped<int(&)[10],  decltype(std::views::common)>);
99       static_assert(!CanBePiped<int(&&)[10], decltype(std::views::common)>);
100       static_assert(!CanBePiped<NotAView,    decltype(std::views::common)>);
101     }
102   }
103 
104   {
105     static_assert(std::same_as<decltype(std::views::common), decltype(std::ranges::views::common)>);
106   }
107 
108   return true;
109 }
110 
111 int main(int, char**) {
112   test();
113   static_assert(test());
114 
115   return 0;
116 }
117