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
10
11// template <class F> unspecified not_fn(F&& f);
12
13#include <functional>
14#include <type_traits>
15#include <string>
16#include <cassert>
17
18#include "test_macros.h"
19#include "type_id.h"
20#include "callable_types.h"
21
22///////////////////////////////////////////////////////////////////////////////
23// BOOL TEST TYPES
24///////////////////////////////////////////////////////////////////////////////
25
26struct EvilBool {
27 static int bang_called;
28
29 EvilBool(EvilBool const&) = default;
30 EvilBool(EvilBool&&) = default;
31
32 friend EvilBool operator!(EvilBool const& other) {
33 ++bang_called;
34 return EvilBool{!other.value};
35 }
36
37private:
38 friend struct MoveOnlyCallable<EvilBool>;
39 friend struct CopyCallable<EvilBool>;
40 friend struct NoExceptCallable<EvilBool>;
41
42 constexpr explicit EvilBool(bool x) : value(x) {}
43 EvilBool& operator=(EvilBool const& other) = default;
44
45public:
46 bool value;
47};
48
49int EvilBool::bang_called = 0;
50
51struct ExplicitBool {
52 ExplicitBool(ExplicitBool const&) = default;
53 ExplicitBool(ExplicitBool&&) = default;
54
55 constexpr explicit operator bool() const { return value; }
56
57private:
58 friend struct MoveOnlyCallable<ExplicitBool>;
59 friend struct CopyCallable<ExplicitBool>;
60
61 constexpr explicit ExplicitBool(bool x) : value(x) {}
62 constexpr ExplicitBool& operator=(bool x) {
63 value = x;
64 return *this;
65 }
66
67 bool value;
68};
69
70
71struct NoExceptEvilBool {
72 NoExceptEvilBool(NoExceptEvilBool const&) = default;
73 NoExceptEvilBool(NoExceptEvilBool&&) = default;
74 NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default;
75
76 constexpr explicit NoExceptEvilBool(bool x) : value(x) {}
77
78 friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
79 return NoExceptEvilBool{!other.value};
80 }
81
82 bool value;
83};
84
85
86
87TEST_CONSTEXPR_CXX20
88bool constructor_tests()
89{
90 {
91 using T = MoveOnlyCallable<bool>;
92 T value(true);
93 using RetT = decltype(std::not_fn(std::move(value)));
94 static_assert(std::is_move_constructible<RetT>::value, "");
95 static_assert(!std::is_copy_constructible<RetT>::value, "");
96 static_assert(!std::is_move_assignable<RetT>::value, "");
97 static_assert(!std::is_copy_assignable<RetT>::value, "");
98 auto ret = std::not_fn(std::move(value));
99 // test it was moved from
100 assert(value.value == false);
101 // test that ret() negates the original value 'true'
102 assert(ret() == false);
103 assert(ret(0, 0.0, "blah") == false);
104 // Move ret and test that it was moved from and that ret2 got the
105 // original value.
106 auto ret2 = std::move(ret);
107 assert(ret() == true);
108 assert(ret2() == false);
109 assert(ret2(42) == false);
110 }
111 {
112 using T = CopyCallable<bool>;
113 T value(false);
114 using RetT = decltype(std::not_fn(value));
115 static_assert(std::is_move_constructible<RetT>::value, "");
116 static_assert(std::is_copy_constructible<RetT>::value, "");
117 static_assert(!std::is_move_assignable<RetT>::value, "");
118 static_assert(!std::is_copy_assignable<RetT>::value, "");
119 auto ret = std::not_fn(value);
120 // test that value is unchanged (copied not moved)
121 assert(value.value == false);
122 // test 'ret' has the original value
123 assert(ret() == true);
124 assert(ret(42, 100) == true);
125 // move from 'ret' and check that 'ret2' has the original value.
126 auto ret2 = std::move(ret);
127 assert(ret() == false);
128 assert(ret2() == true);
129 assert(ret2("abc") == true);
130 // initialize not_fn with rvalue
131 auto ret3 = std::not_fn(std::move(value));
132 assert(ret(0) == false);
133 assert(ret3(0) == true);
134 }
135 {
136 using T = CopyAssignableWrapper;
137 T value(true);
138 T value2(false);
139 using RetT = decltype(std::not_fn(value));
140 static_assert(std::is_move_constructible<RetT>::value, "");
141 static_assert(std::is_copy_constructible<RetT>::value, "");
142 auto ret = std::not_fn(value);
143 assert(ret() == false);
144 auto ret2 = std::not_fn(value2);
145 assert(ret2() == true);
146 }
147 {
148 using T = MoveAssignableWrapper;
149 T value(true);
150 T value2(false);
151 using RetT = decltype(std::not_fn(std::move(value)));
152 static_assert(std::is_move_constructible<RetT>::value, "");
153 static_assert(!std::is_copy_constructible<RetT>::value, "");
154 static_assert(!std::is_copy_assignable<RetT>::value, "");
155 auto ret = std::not_fn(std::move(value));
156 assert(ret() == false);
157 auto ret2 = std::not_fn(std::move(value2));
158 assert(ret2() == true);
159 }
160 return true;
161}
162
163void return_type_tests()
164{
165 using std::is_same;
166 {
167 using T = CopyCallable<bool>;
168 auto ret = std::not_fn(T{false});
169 static_assert(is_same<decltype(ret()), bool>::value, "");
170 static_assert(is_same<decltype(ret("abc")), bool>::value, "");
171 assert(ret() == true);
172 }
173 {
174 using T = CopyCallable<ExplicitBool>;
175 auto ret = std::not_fn(T{true});
176 static_assert(is_same<decltype(ret()), bool>::value, "");
177 static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, "");
178 assert(ret() == false);
179 }
180 {
181 using T = CopyCallable<EvilBool>;
182 auto ret = std::not_fn(T{false});
183 static_assert(is_same<decltype(ret()), EvilBool>::value, "");
184 EvilBool::bang_called = 0;
185 auto value_ret = ret();
186 assert(EvilBool::bang_called == 1);
187 assert(value_ret.value == true);
188 ret();
189 assert(EvilBool::bang_called == 2);
190 }
191}
192
193// Other tests only test using objects with call operators. Test various
194// other callable types here.
195TEST_CONSTEXPR_CXX20
196bool other_callable_types_test()
197{
198 { // test with function pointer
199 auto ret = std::not_fn(returns_true);
200 assert(ret() == false);
201 }
202 { // test with lambda
203 auto returns_value = [](bool value) { return value; };
204 auto ret = std::not_fn(fn&: returns_value);
205 assert(ret(true) == false);
206 assert(ret(false) == true);
207 }
208 { // test with pointer to member function
209 MemFunCallable mt(true);
210 const MemFunCallable mf(false);
211 auto ret = std::not_fn(&MemFunCallable::return_value);
212 assert(ret(mt) == false);
213 assert(ret(mf) == true);
214 assert(ret(&mt) == false);
215 assert(ret(&mf) == true);
216 }
217 { // test with pointer to member function
218 MemFunCallable mt(true);
219 MemFunCallable mf(false);
220 auto ret = std::not_fn(&MemFunCallable::return_value_nc);
221 assert(ret(mt) == false);
222 assert(ret(mf) == true);
223 assert(ret(&mt) == false);
224 assert(ret(&mf) == true);
225 }
226 { // test with pointer to member data
227 MemFunCallable mt(true);
228 const MemFunCallable mf(false);
229 auto ret = std::not_fn(&MemFunCallable::value);
230 assert(ret(mt) == false);
231 assert(ret(mf) == true);
232 assert(ret(&mt) == false);
233 assert(ret(&mf) == true);
234 }
235 return true;
236}
237
238void throws_in_constructor_test()
239{
240#ifndef TEST_HAS_NO_EXCEPTIONS
241 struct ThrowsOnCopy {
242 ThrowsOnCopy(ThrowsOnCopy const&) {
243 throw 42;
244 }
245 ThrowsOnCopy() = default;
246 bool operator()() const {
247 assert(false);
248#ifdef TEST_COMPILER_MSVC
249 __assume(0);
250#else
251 __builtin_unreachable();
252#endif
253 }
254 };
255 {
256 ThrowsOnCopy cp;
257 try {
258 (void)std::not_fn(fn&: cp);
259 assert(false);
260 } catch (int const& value) {
261 assert(value == 42);
262 }
263 }
264#endif
265}
266
267TEST_CONSTEXPR_CXX20
268bool call_operator_sfinae_test() {
269 { // wrong number of arguments
270 using T = decltype(std::not_fn(returns_true));
271 static_assert(std::is_invocable<T>::value, ""); // callable only with no args
272 static_assert(!std::is_invocable<T, bool>::value, "");
273 }
274 { // violates const correctness (member function pointer)
275 using T = decltype(std::not_fn(&MemFunCallable::return_value_nc));
276 static_assert(std::is_invocable<T, MemFunCallable&>::value, "");
277 static_assert(!std::is_invocable<T, const MemFunCallable&>::value, "");
278 }
279 { // violates const correctness (call object)
280 using Obj = CopyCallable<bool>;
281 using NCT = decltype(std::not_fn(Obj{true}));
282 using CT = const NCT;
283 static_assert(std::is_invocable<NCT>::value, "");
284 static_assert(!std::is_invocable<CT>::value, "");
285 }
286 { // returns bad type with no operator!
287 auto fn = [](auto x) { return x; };
288 using T = decltype(std::not_fn(fn&: fn));
289 static_assert(std::is_invocable<T, bool>::value, "");
290 static_assert(!std::is_invocable<T, std::string>::value, "");
291 }
292 return true;
293}
294
295TEST_CONSTEXPR_CXX20
296bool call_operator_forwarding_test()
297{
298 using Fn = ForwardingCallObject;
299 Fn::State st;
300 auto obj = std::not_fn(Fn{st});
301 const auto& c_obj = obj;
302 { // test zero args
303 obj();
304 assert(st.check_call<>(CT_NonConst | CT_LValue));
305 std::move(obj)();
306 assert(st.check_call<>(CT_NonConst | CT_RValue));
307 c_obj();
308 assert(st.check_call<>(CT_Const | CT_LValue));
309 std::move(c_obj)();
310 assert(st.check_call<>(CT_Const | CT_RValue));
311 }
312 { // test value categories
313 int x = 42;
314 const int cx = 42;
315 obj(x);
316 assert(st.check_call<int&>(CT_NonConst | CT_LValue));
317 obj(cx);
318 assert(st.check_call<const int&>(CT_NonConst | CT_LValue));
319 obj(std::move(x));
320 assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
321 obj(std::move(cx));
322 assert(st.check_call<const int&&>(CT_NonConst | CT_LValue));
323 obj(42);
324 assert(st.check_call<int&&>(CT_NonConst | CT_LValue));
325 }
326 { // test value categories - rvalue
327 int x = 42;
328 const int cx = 42;
329 std::move(obj)(x);
330 assert(st.check_call<int&>(CT_NonConst | CT_RValue));
331 std::move(obj)(cx);
332 assert(st.check_call<const int&>(CT_NonConst | CT_RValue));
333 std::move(obj)(std::move(x));
334 assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
335 std::move(obj)(std::move(cx));
336 assert(st.check_call<const int&&>(CT_NonConst | CT_RValue));
337 std::move(obj)(42);
338 assert(st.check_call<int&&>(CT_NonConst | CT_RValue));
339 }
340 { // test value categories - const call
341 int x = 42;
342 const int cx = 42;
343 c_obj(x);
344 assert(st.check_call<int&>(CT_Const | CT_LValue));
345 c_obj(cx);
346 assert(st.check_call<const int&>(CT_Const | CT_LValue));
347 c_obj(std::move(x));
348 assert(st.check_call<int&&>(CT_Const | CT_LValue));
349 c_obj(std::move(cx));
350 assert(st.check_call<const int&&>(CT_Const | CT_LValue));
351 c_obj(42);
352 assert(st.check_call<int&&>(CT_Const | CT_LValue));
353 }
354 { // test value categories - const call rvalue
355 int x = 42;
356 const int cx = 42;
357 std::move(c_obj)(x);
358 assert(st.check_call<int&>(CT_Const | CT_RValue));
359 std::move(c_obj)(cx);
360 assert(st.check_call<const int&>(CT_Const | CT_RValue));
361 std::move(c_obj)(std::move(x));
362 assert(st.check_call<int&&>(CT_Const | CT_RValue));
363 std::move(c_obj)(std::move(cx));
364 assert(st.check_call<const int&&>(CT_Const | CT_RValue));
365 std::move(c_obj)(42);
366 assert(st.check_call<int&&>(CT_Const | CT_RValue));
367 }
368 { // test multi arg
369 using String = const char *;
370 const double y = 3.14;
371 String s = "abc";
372 obj(42, std::move(y), s, String{"foo"});
373 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_LValue)));
374 std::move(obj)(42, std::move(y), s, String{"foo"});
375 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_RValue)));
376 c_obj(42, std::move(y), s, String{"foo"});
377 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_LValue)));
378 std::move(c_obj)(42, std::move(y), s, String{"foo"});
379 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_RValue)));
380 }
381 return true;
382}
383
384TEST_CONSTEXPR_CXX20
385bool call_operator_noexcept_test()
386{
387 {
388 using T = ConstCallable<bool>;
389 T value(true);
390 auto ret = std::not_fn(value);
391 static_assert(!noexcept(ret()), "call should not be noexcept");
392 auto const& cret = ret;
393 static_assert(!noexcept(cret()), "call should not be noexcept");
394 }
395 {
396 using T = NoExceptCallable<bool>;
397 T value(true);
398 auto ret = std::not_fn(value);
399 LIBCPP_STATIC_ASSERT(noexcept(!std::__invoke(value)), "");
400#if TEST_STD_VER > 14
401 static_assert(noexcept(!std::invoke(value)), "");
402#endif
403 static_assert(noexcept(ret()), "call should be noexcept");
404 auto const& cret = ret;
405 static_assert(noexcept(cret()), "call should be noexcept");
406 }
407 {
408 using T = NoExceptCallable<NoExceptEvilBool>;
409 T value(true);
410 auto ret = std::not_fn(value);
411 static_assert(noexcept(ret()), "call should not be noexcept");
412 auto const& cret = ret;
413 static_assert(noexcept(cret()), "call should not be noexcept");
414 }
415 {
416 using T = NoExceptCallable<EvilBool>;
417 T value(true);
418 auto ret = std::not_fn(value);
419 static_assert(!noexcept(ret()), "call should not be noexcept");
420 auto const& cret = ret;
421 static_assert(!noexcept(cret()), "call should not be noexcept");
422 }
423 return true;
424}
425
426TEST_CONSTEXPR_CXX20
427bool test_lwg2767() {
428 // See https://cplusplus.github.io/LWG/lwg-defects.html#2767
429 struct Abstract { virtual void f() const = 0; };
430 struct Derived : public Abstract { void f() const {} };
431 struct F { constexpr bool operator()(Abstract&&) { return false; } };
432 {
433 Derived d;
434 Abstract &a = d;
435 bool b = std::not_fn(fn: F{})(std::move(a));
436 assert(b);
437 }
438 return true;
439}
440
441int main(int, char**)
442{
443 constructor_tests();
444 return_type_tests();
445 other_callable_types_test();
446 throws_in_constructor_test();
447 call_operator_sfinae_test(); // somewhat of an extension
448 call_operator_forwarding_test();
449 call_operator_noexcept_test();
450 test_lwg2767();
451
452#if TEST_STD_VER >= 20
453 static_assert(constructor_tests());
454 static_assert(other_callable_types_test());
455 static_assert(call_operator_sfinae_test()); // somewhat of an extension
456 static_assert(call_operator_forwarding_test());
457 static_assert(call_operator_noexcept_test());
458 static_assert(test_lwg2767());
459#endif
460
461 return 0;
462}
463

source code of libcxx/test/std/utilities/function.objects/func.not_fn/not_fn.pass.cpp