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