1 // Copyright (C) 2021-2023 Free Software Foundation, Inc.
3 // This file is part of the GNU ISO C++ Library. This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3. If not see
16 // <http://www.gnu.org/licenses/>.
18 // { dg-options "-std=gnu++2a" }
19 // { dg-do compile { target c++2a } }
21 // PR libstdc++/100577
29 namespace ranges
= std::ranges
;
30 namespace views
= std::ranges::views
;
35 // Verify adaptors are deemed to have simple extra arguments when appropriate.
36 using views::__adaptor::__adaptor_has_simple_extra_args
;
38 static_assert(__adaptor_has_simple_extra_args
<decltype(views::transform
), identity
>);
39 static_assert(__adaptor_has_simple_extra_args
<decltype(views::filter
), identity
>);
40 static_assert(__adaptor_has_simple_extra_args
<decltype(views::drop
), int>);
41 static_assert(__adaptor_has_simple_extra_args
<decltype(views::take
), int>);
42 static_assert(__adaptor_has_simple_extra_args
<decltype(views::take_while
), identity
>);
43 static_assert(__adaptor_has_simple_extra_args
<decltype(views::drop_while
), identity
>);
44 static_assert(__adaptor_has_simple_extra_args
<decltype(views::lazy_split
), char>);
46 static_assert(__adaptor_has_simple_extra_args
<decltype(views::lazy_split
), std::string_view
>);
47 static_assert(!__adaptor_has_simple_extra_args
<decltype(views::lazy_split
), std::string
>);
50 using views::__adaptor::__closure_has_simple_call_op
;
51 __closure_has_simple_call_op
auto a00
= views::all
;
52 __closure_has_simple_call_op
auto a01
= views::transform(std::identity
{});
53 __closure_has_simple_call_op
auto a02
= views::filter(std::identity
{});
54 __closure_has_simple_call_op
auto a03
= views::drop(42);
55 __closure_has_simple_call_op
auto a04
= views::take(42);
56 __closure_has_simple_call_op
auto a05
= views::take_while(std::identity
{});
57 __closure_has_simple_call_op
auto a06
= views::drop_while(std::identity
{});
58 __closure_has_simple_call_op
auto a07
= views::join
;
59 __closure_has_simple_call_op
auto a08
= views::common
;
60 __closure_has_simple_call_op
auto a09
= views::reverse
;
61 __closure_has_simple_call_op
auto a10
= views::keys
;
62 __closure_has_simple_call_op
auto a11
= views::lazy_split(' ');
63 __closure_has_simple_call_op
auto a11a
= views::split(' ');
64 // Verify composition of simple closures is simple.
65 __closure_has_simple_call_op
auto b
66 = (a00
| a01
) | (a02
| a03
) | (a04
| a05
| a06
) | (a07
| a08
| a09
| a10
) | a11
;
69 // Verify views::lazy_split(non_view_range) is an exception.
71 auto a12
= views::lazy_split(s
);
72 static_assert(!__closure_has_simple_call_op
<decltype(a12
)>);
73 static_assert(!__closure_has_simple_call_op
<decltype(a12
| a00
)>);
74 static_assert(!__closure_has_simple_call_op
<decltype(a00
| a12
)>);
76 // Likewise views::split(non_view_range).
77 auto a12a
= views::split(s
);
78 static_assert(!__closure_has_simple_call_op
<decltype(a12a
)>);
79 static_assert(!__closure_has_simple_call_op
<decltype(a12a
| a00
)>);
80 static_assert(!__closure_has_simple_call_op
<decltype(a00
| a12a
)>);
87 // Range adaptor closures with a simple operator() aren't implemented using a
88 // fallback deleted overload, so when a call is ill-formed overload resolution
92 views::transform(badarg
)(x
); // { dg-error "no match" }
93 views::filter(badarg
)(x
); // { dg-error "no match" }
94 views::take_while(badarg
)(x
); // { dg-error "no match" }
95 views::drop_while(badarg
)(x
); // { dg-error "no match" }
97 (views::transform(badarg
) | views::all
)(x
); // { dg-error "no match" }
98 (views::filter(badarg
) | views::all
)(x
); // { dg-error "no match" }
99 (views::take_while(badarg
) | views::all
)(x
); // { dg-error "no match" }
100 (views::drop_while(badarg
) | views::all
)(x
); // { dg-error "no match" }
102 // In practice, range adaptor closures with non-simple operator() are
103 // implemented using a fallback deleted overload, so when a call is
104 // ill-formed overload resolution succeeds but selects the deleted overload
105 // (but only when the closure is invoked as an rvalue).
106 views::lazy_split(badarg
)(x
); // { dg-error "deleted function" }
107 (views::lazy_split(badarg
) | views::all
)(x
); // { dg-error "deleted function" }
108 auto a0
= views::lazy_split(badarg
);
109 a0(x
); // { dg-error "no match" };
110 auto a1
= a0
| views::all
;
111 a1(x
); // { dg-error "no match" }
113 views::split(badarg
)(x
); // { dg-error "deleted function" }
114 (views::split(badarg
) | views::all
)(x
); // { dg-error "deleted function" }
115 auto a0a
= views::split(badarg
);
116 a0a(x
); // { dg-error "no match" };
117 auto a1a
= a0a
| views::all
;
118 a1a(x
); // { dg-error "no match" }
120 views::take(badarg
)(x
); // { dg-error "deleted" }
121 views::drop(badarg
)(x
); // { dg-error "deleted" }
122 (views::take(badarg
) | views::all
)(x
); // { dg-error "deleted" }
123 (views::drop(badarg
) | views::all
)(x
); // { dg-error "deleted" }
129 // PR libstdc++/100940
131 struct S
{ operator int() && { return 5; }; };
132 x
| std::views::take(S
{});
133 x
| std::views::drop(S
{});
140 // Non-trivially-copyable extra arguments make a closure not simple.
141 using F
= std::function
<bool(bool)>;
142 static_assert(!std::is_trivially_copyable_v
<F
>);
143 using views::__adaptor::__closure_has_simple_call_op
;
144 static_assert(!__closure_has_simple_call_op
<decltype(views::take_while(std::declval
<F
>()))>);
145 static_assert(!__closure_has_simple_call_op
<decltype(views::drop_while(std::declval
<F
>()))>);
146 static_assert(!__closure_has_simple_call_op
<decltype(views::filter(std::declval
<F
>()))>);
147 static_assert(!__closure_has_simple_call_op
<decltype(views::transform(std::declval
<F
>()))>);
151 // { dg-prune-output "in requirements" }