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
21
22 ///////////////////////////////////////////////////////////////////////////////
23 // CALLABLE TEST TYPES
24 ///////////////////////////////////////////////////////////////////////////////
25
returns_true()26 bool returns_true() { return true; }
27
28 template <class Ret = bool>
29 struct MoveOnlyCallable {
30 MoveOnlyCallable(MoveOnlyCallable const&) = delete;
MoveOnlyCallableMoveOnlyCallable31 MoveOnlyCallable(MoveOnlyCallable&& other)
32 : value(other.value)
33 { other.value = !other.value; }
34
35 template <class ...Args>
operator ()MoveOnlyCallable36 Ret operator()(Args&&...) { return Ret{value}; }
37
MoveOnlyCallableMoveOnlyCallable38 explicit MoveOnlyCallable(bool x) : value(x) {}
39 Ret value;
40 };
41
42 template <class Ret = bool>
43 struct CopyCallable {
CopyCallableCopyCallable44 CopyCallable(CopyCallable const& other)
45 : value(other.value) {}
46
CopyCallableCopyCallable47 CopyCallable(CopyCallable&& other)
48 : value(other.value) { other.value = !other.value; }
49
50 template <class ...Args>
operator ()CopyCallable51 Ret operator()(Args&&...) { return Ret{value}; }
52
CopyCallableCopyCallable53 explicit CopyCallable(bool x) : value(x) {}
54 Ret value;
55 };
56
57
58 template <class Ret = bool>
59 struct ConstCallable {
ConstCallableConstCallable60 ConstCallable(ConstCallable const& other)
61 : value(other.value) {}
62
ConstCallableConstCallable63 ConstCallable(ConstCallable&& other)
64 : value(other.value) { other.value = !other.value; }
65
66 template <class ...Args>
operator ()ConstCallable67 Ret operator()(Args&&...) const { return Ret{value}; }
68
ConstCallableConstCallable69 explicit ConstCallable(bool x) : value(x) {}
70 Ret value;
71 };
72
73
74
75 template <class Ret = bool>
76 struct NoExceptCallable {
NoExceptCallableNoExceptCallable77 NoExceptCallable(NoExceptCallable const& other)
78 : value(other.value) {}
79
80 template <class ...Args>
operator ()NoExceptCallable81 Ret operator()(Args&&...) noexcept { return Ret{value}; }
82
83 template <class ...Args>
operator ()NoExceptCallable84 Ret operator()(Args&&...) const noexcept { return Ret{value}; }
85
NoExceptCallableNoExceptCallable86 explicit NoExceptCallable(bool x) : value(x) {}
87 Ret value;
88 };
89
90 struct CopyAssignableWrapper {
91 CopyAssignableWrapper(CopyAssignableWrapper const&) = default;
92 CopyAssignableWrapper(CopyAssignableWrapper&&) = default;
93 CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default;
94 CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default;
95
96 template <class ...Args>
operator ()CopyAssignableWrapper97 bool operator()(Args&&...) { return value; }
98
CopyAssignableWrapperCopyAssignableWrapper99 explicit CopyAssignableWrapper(bool x) : value(x) {}
100 bool value;
101 };
102
103
104 struct MoveAssignableWrapper {
105 MoveAssignableWrapper(MoveAssignableWrapper const&) = delete;
106 MoveAssignableWrapper(MoveAssignableWrapper&&) = default;
107 MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete;
108 MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default;
109
110 template <class ...Args>
operator ()MoveAssignableWrapper111 bool operator()(Args&&...) { return value; }
112
MoveAssignableWrapperMoveAssignableWrapper113 explicit MoveAssignableWrapper(bool x) : value(x) {}
114 bool value;
115 };
116
117 struct MemFunCallable {
MemFunCallableMemFunCallable118 explicit MemFunCallable(bool x) : value(x) {}
119
return_valueMemFunCallable120 bool return_value() const { return value; }
return_value_ncMemFunCallable121 bool return_value_nc() { return value; }
122 bool value;
123 };
124
125 enum CallType : unsigned {
126 CT_None,
127 CT_NonConst = 1,
128 CT_Const = 2,
129 CT_LValue = 4,
130 CT_RValue = 8
131 };
132
operator |(CallType LHS,CallType RHS)133 inline constexpr CallType operator|(CallType LHS, CallType RHS) {
134 return static_cast<CallType>(static_cast<unsigned>(LHS) | static_cast<unsigned>(RHS));
135 }
136
137 struct ForwardingCallObject {
138
139 template <class ...Args>
operator ()ForwardingCallObject140 bool operator()(Args&&...) & {
141 set_call<Args&&...>(CT_NonConst | CT_LValue);
142 return true;
143 }
144
145 template <class ...Args>
operator ()ForwardingCallObject146 bool operator()(Args&&...) const & {
147 set_call<Args&&...>(CT_Const | CT_LValue);
148 return true;
149 }
150
151 // Don't allow the call operator to be invoked as an rvalue.
152 template <class ...Args>
operator ()ForwardingCallObject153 bool operator()(Args&&...) && {
154 set_call<Args&&...>(CT_NonConst | CT_RValue);
155 return true;
156 }
157
158 template <class ...Args>
operator ()ForwardingCallObject159 bool operator()(Args&&...) const && {
160 set_call<Args&&...>(CT_Const | CT_RValue);
161 return true;
162 }
163
164 template <class ...Args>
set_callForwardingCallObject165 static void set_call(CallType type) {
166 assert(last_call_type == CT_None);
167 assert(last_call_args == nullptr);
168 last_call_type = type;
169 last_call_args = &makeArgumentID<Args...>();
170 }
171
172 template <class ...Args>
check_callForwardingCallObject173 static bool check_call(CallType type) {
174 bool result =
175 last_call_type == type
176 && last_call_args
177 && *last_call_args == makeArgumentID<Args...>();
178 last_call_type = CT_None;
179 last_call_args = nullptr;
180 return result;
181 }
182
183 static CallType last_call_type;
184 static TypeID const* last_call_args;
185 };
186
187 CallType ForwardingCallObject::last_call_type = CT_None;
188 TypeID const* ForwardingCallObject::last_call_args = nullptr;
189
190
191
192 ///////////////////////////////////////////////////////////////////////////////
193 // BOOL TEST TYPES
194 ///////////////////////////////////////////////////////////////////////////////
195
196 struct EvilBool {
197 static int bang_called;
198
199 EvilBool(EvilBool const&) = default;
200 EvilBool(EvilBool&&) = default;
201
operator !(EvilBool const & other)202 friend EvilBool operator!(EvilBool const& other) {
203 ++bang_called;
204 return EvilBool{!other.value};
205 }
206
207 private:
208 friend struct MoveOnlyCallable<EvilBool>;
209 friend struct CopyCallable<EvilBool>;
210 friend struct NoExceptCallable<EvilBool>;
211
EvilBoolEvilBool212 explicit EvilBool(bool x) : value(x) {}
213 EvilBool& operator=(EvilBool const& other) = default;
214
215 public:
216 bool value;
217 };
218
219 int EvilBool::bang_called = 0;
220
221 struct ExplicitBool {
222 ExplicitBool(ExplicitBool const&) = default;
223 ExplicitBool(ExplicitBool&&) = default;
224
operator boolExplicitBool225 explicit operator bool() const { return value; }
226
227 private:
228 friend struct MoveOnlyCallable<ExplicitBool>;
229 friend struct CopyCallable<ExplicitBool>;
230
ExplicitBoolExplicitBool231 explicit ExplicitBool(bool x) : value(x) {}
operator =ExplicitBool232 ExplicitBool& operator=(bool x) {
233 value = x;
234 return *this;
235 }
236
237 bool value;
238 };
239
240
241 struct NoExceptEvilBool {
242 NoExceptEvilBool(NoExceptEvilBool const&) = default;
243 NoExceptEvilBool(NoExceptEvilBool&&) = default;
244 NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default;
245
NoExceptEvilBoolNoExceptEvilBool246 explicit NoExceptEvilBool(bool x) : value(x) {}
247
operator !(NoExceptEvilBool const & other)248 friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept {
249 return NoExceptEvilBool{!other.value};
250 }
251
252 bool value;
253 };
254
255
256
constructor_tests()257 void constructor_tests()
258 {
259 {
260 using T = MoveOnlyCallable<bool>;
261 T value(true);
262 using RetT = decltype(std::not_fn(std::move(value)));
263 static_assert(std::is_move_constructible<RetT>::value, "");
264 static_assert(!std::is_copy_constructible<RetT>::value, "");
265 static_assert(!std::is_move_assignable<RetT>::value, "");
266 static_assert(!std::is_copy_assignable<RetT>::value, "");
267 auto ret = std::not_fn(std::move(value));
268 // test it was moved from
269 assert(value.value == false);
270 // test that ret() negates the original value 'true'
271 assert(ret() == false);
272 assert(ret(0, 0.0, "blah") == false);
273 // Move ret and test that it was moved from and that ret2 got the
274 // original value.
275 auto ret2 = std::move(ret);
276 assert(ret() == true);
277 assert(ret2() == false);
278 assert(ret2(42) == false);
279 }
280 {
281 using T = CopyCallable<bool>;
282 T value(false);
283 using RetT = decltype(std::not_fn(value));
284 static_assert(std::is_move_constructible<RetT>::value, "");
285 static_assert(std::is_copy_constructible<RetT>::value, "");
286 static_assert(!std::is_move_assignable<RetT>::value, "");
287 static_assert(!std::is_copy_assignable<RetT>::value, "");
288 auto ret = std::not_fn(value);
289 // test that value is unchanged (copied not moved)
290 assert(value.value == false);
291 // test 'ret' has the original value
292 assert(ret() == true);
293 assert(ret(42, 100) == true);
294 // move from 'ret' and check that 'ret2' has the original value.
295 auto ret2 = std::move(ret);
296 assert(ret() == false);
297 assert(ret2() == true);
298 assert(ret2("abc") == true);
299 }
300 {
301 using T = CopyAssignableWrapper;
302 T value(true);
303 T value2(false);
304 using RetT = decltype(std::not_fn(value));
305 static_assert(std::is_move_constructible<RetT>::value, "");
306 static_assert(std::is_copy_constructible<RetT>::value, "");
307 LIBCPP_STATIC_ASSERT(std::is_move_assignable<RetT>::value, "");
308 LIBCPP_STATIC_ASSERT(std::is_copy_assignable<RetT>::value, "");
309 auto ret = std::not_fn(value);
310 assert(ret() == false);
311 auto ret2 = std::not_fn(value2);
312 assert(ret2() == true);
313 #if defined(_LIBCPP_VERSION)
314 ret = ret2;
315 assert(ret() == true);
316 assert(ret2() == true);
317 #endif // _LIBCPP_VERSION
318 }
319 {
320 using T = MoveAssignableWrapper;
321 T value(true);
322 T value2(false);
323 using RetT = decltype(std::not_fn(std::move(value)));
324 static_assert(std::is_move_constructible<RetT>::value, "");
325 static_assert(!std::is_copy_constructible<RetT>::value, "");
326 LIBCPP_STATIC_ASSERT(std::is_move_assignable<RetT>::value, "");
327 static_assert(!std::is_copy_assignable<RetT>::value, "");
328 auto ret = std::not_fn(std::move(value));
329 assert(ret() == false);
330 auto ret2 = std::not_fn(std::move(value2));
331 assert(ret2() == true);
332 #if defined(_LIBCPP_VERSION)
333 ret = std::move(ret2);
334 assert(ret() == true);
335 #endif // _LIBCPP_VERSION
336 }
337 }
338
return_type_tests()339 void return_type_tests()
340 {
341 using std::is_same;
342 {
343 using T = CopyCallable<bool>;
344 auto ret = std::not_fn(T{false});
345 static_assert(is_same<decltype(ret()), bool>::value, "");
346 static_assert(is_same<decltype(ret("abc")), bool>::value, "");
347 assert(ret() == true);
348 }
349 {
350 using T = CopyCallable<ExplicitBool>;
351 auto ret = std::not_fn(T{true});
352 static_assert(is_same<decltype(ret()), bool>::value, "");
353 static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, "");
354 assert(ret() == false);
355 }
356 {
357 using T = CopyCallable<EvilBool>;
358 auto ret = std::not_fn(T{false});
359 static_assert(is_same<decltype(ret()), EvilBool>::value, "");
360 EvilBool::bang_called = 0;
361 auto value_ret = ret();
362 assert(EvilBool::bang_called == 1);
363 assert(value_ret.value == true);
364 ret();
365 assert(EvilBool::bang_called == 2);
366 }
367 }
368
369 // Other tests only test using objects with call operators. Test various
370 // other callable types here.
other_callable_types_test()371 void other_callable_types_test()
372 {
373 { // test with function pointer
374 auto ret = std::not_fn(returns_true);
375 assert(ret() == false);
376 }
377 { // test with lambda
378 auto returns_value = [](bool value) { return value; };
379 auto ret = std::not_fn(returns_value);
380 assert(ret(true) == false);
381 assert(ret(false) == true);
382 }
383 { // test with pointer to member function
384 MemFunCallable mt(true);
385 const MemFunCallable mf(false);
386 auto ret = std::not_fn(&MemFunCallable::return_value);
387 assert(ret(mt) == false);
388 assert(ret(mf) == true);
389 assert(ret(&mt) == false);
390 assert(ret(&mf) == true);
391 }
392 { // test with pointer to member function
393 MemFunCallable mt(true);
394 MemFunCallable mf(false);
395 auto ret = std::not_fn(&MemFunCallable::return_value_nc);
396 assert(ret(mt) == false);
397 assert(ret(mf) == true);
398 assert(ret(&mt) == false);
399 assert(ret(&mf) == true);
400 }
401 { // test with pointer to member data
402 MemFunCallable mt(true);
403 const MemFunCallable mf(false);
404 auto ret = std::not_fn(&MemFunCallable::value);
405 assert(ret(mt) == false);
406 assert(ret(mf) == true);
407 assert(ret(&mt) == false);
408 assert(ret(&mf) == true);
409 }
410 }
411
throws_in_constructor_test()412 void throws_in_constructor_test()
413 {
414 #ifndef TEST_HAS_NO_EXCEPTIONS
415 struct ThrowsOnCopy {
416 ThrowsOnCopy(ThrowsOnCopy const&) {
417 throw 42;
418 }
419 ThrowsOnCopy() = default;
420 bool operator()() const {
421 assert(false);
422 #if defined(TEST_COMPILER_C1XX)
423 __assume(0);
424 #else
425 __builtin_unreachable();
426 #endif
427 }
428 };
429 {
430 ThrowsOnCopy cp;
431 try {
432 (void)std::not_fn(cp);
433 assert(false);
434 } catch (int const& value) {
435 assert(value == 42);
436 }
437 }
438 #endif
439 }
440
call_operator_sfinae_test()441 void call_operator_sfinae_test() {
442 { // wrong number of arguments
443 using T = decltype(std::not_fn(returns_true));
444 static_assert(std::is_invocable<T>::value, ""); // callable only with no args
445 static_assert(!std::is_invocable<T, bool>::value, "");
446 }
447 { // violates const correctness (member function pointer)
448 using T = decltype(std::not_fn(&MemFunCallable::return_value_nc));
449 static_assert(std::is_invocable<T, MemFunCallable&>::value, "");
450 static_assert(!std::is_invocable<T, const MemFunCallable&>::value, "");
451 }
452 { // violates const correctness (call object)
453 using Obj = CopyCallable<bool>;
454 using NCT = decltype(std::not_fn(Obj{true}));
455 using CT = const NCT;
456 static_assert(std::is_invocable<NCT>::value, "");
457 static_assert(!std::is_invocable<CT>::value, "");
458 }
459 { // returns bad type with no operator!
460 auto fn = [](auto x) { return x; };
461 using T = decltype(std::not_fn(fn));
462 static_assert(std::is_invocable<T, bool>::value, "");
463 static_assert(!std::is_invocable<T, std::string>::value, "");
464 }
465 }
466
call_operator_forwarding_test()467 void call_operator_forwarding_test()
468 {
469 using Fn = ForwardingCallObject;
470 auto obj = std::not_fn(Fn{});
471 const auto& c_obj = obj;
472 { // test zero args
473 obj();
474 assert(Fn::check_call<>(CT_NonConst | CT_LValue));
475 std::move(obj)();
476 assert(Fn::check_call<>(CT_NonConst | CT_RValue));
477 c_obj();
478 assert(Fn::check_call<>(CT_Const | CT_LValue));
479 std::move(c_obj)();
480 assert(Fn::check_call<>(CT_Const | CT_RValue));
481 }
482 { // test value categories
483 int x = 42;
484 const int cx = 42;
485 obj(x);
486 assert(Fn::check_call<int&>(CT_NonConst | CT_LValue));
487 obj(cx);
488 assert(Fn::check_call<const int&>(CT_NonConst | CT_LValue));
489 obj(std::move(x));
490 assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
491 obj(std::move(cx));
492 assert(Fn::check_call<const int&&>(CT_NonConst | CT_LValue));
493 obj(42);
494 assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue));
495 }
496 { // test value categories - rvalue
497 int x = 42;
498 const int cx = 42;
499 std::move(obj)(x);
500 assert(Fn::check_call<int&>(CT_NonConst | CT_RValue));
501 std::move(obj)(cx);
502 assert(Fn::check_call<const int&>(CT_NonConst | CT_RValue));
503 std::move(obj)(std::move(x));
504 assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
505 std::move(obj)(std::move(cx));
506 assert(Fn::check_call<const int&&>(CT_NonConst | CT_RValue));
507 std::move(obj)(42);
508 assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue));
509 }
510 { // test value categories - const call
511 int x = 42;
512 const int cx = 42;
513 c_obj(x);
514 assert(Fn::check_call<int&>(CT_Const | CT_LValue));
515 c_obj(cx);
516 assert(Fn::check_call<const int&>(CT_Const | CT_LValue));
517 c_obj(std::move(x));
518 assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
519 c_obj(std::move(cx));
520 assert(Fn::check_call<const int&&>(CT_Const | CT_LValue));
521 c_obj(42);
522 assert(Fn::check_call<int&&>(CT_Const | CT_LValue));
523 }
524 { // test value categories - const call rvalue
525 int x = 42;
526 const int cx = 42;
527 std::move(c_obj)(x);
528 assert(Fn::check_call<int&>(CT_Const | CT_RValue));
529 std::move(c_obj)(cx);
530 assert(Fn::check_call<const int&>(CT_Const | CT_RValue));
531 std::move(c_obj)(std::move(x));
532 assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
533 std::move(c_obj)(std::move(cx));
534 assert(Fn::check_call<const int&&>(CT_Const | CT_RValue));
535 std::move(c_obj)(42);
536 assert(Fn::check_call<int&&>(CT_Const | CT_RValue));
537 }
538 { // test multi arg
539 const double y = 3.14;
540 std::string s = "abc";
541 obj(42, std::move(y), s, std::string{"foo"});
542 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_LValue);
543 std::move(obj)(42, std::move(y), s, std::string{"foo"});
544 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_RValue);
545 c_obj(42, std::move(y), s, std::string{"foo"});
546 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_LValue);
547 std::move(c_obj)(42, std::move(y), s, std::string{"foo"});
548 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_RValue);
549 }
550 }
551
call_operator_noexcept_test()552 void call_operator_noexcept_test()
553 {
554 {
555 using T = ConstCallable<bool>;
556 T value(true);
557 auto ret = std::not_fn(value);
558 static_assert(!noexcept(ret()), "call should not be noexcept");
559 auto const& cret = ret;
560 static_assert(!noexcept(cret()), "call should not be noexcept");
561 }
562 {
563 using T = NoExceptCallable<bool>;
564 T value(true);
565 auto ret = std::not_fn(value);
566 LIBCPP_STATIC_ASSERT(noexcept(!_VSTD::__invoke(value)), "");
567 #if TEST_STD_VER > 14
568 static_assert(noexcept(!std::invoke(value)), "");
569 #endif
570 static_assert(noexcept(ret()), "call should be noexcept");
571 auto const& cret = ret;
572 static_assert(noexcept(cret()), "call should be noexcept");
573 }
574 {
575 using T = NoExceptCallable<NoExceptEvilBool>;
576 T value(true);
577 auto ret = std::not_fn(value);
578 static_assert(noexcept(ret()), "call should not be noexcept");
579 auto const& cret = ret;
580 static_assert(noexcept(cret()), "call should not be noexcept");
581 }
582 {
583 using T = NoExceptCallable<EvilBool>;
584 T value(true);
585 auto ret = std::not_fn(value);
586 static_assert(!noexcept(ret()), "call should not be noexcept");
587 auto const& cret = ret;
588 static_assert(!noexcept(cret()), "call should not be noexcept");
589 }
590 }
591
test_lwg2767()592 void test_lwg2767() {
593 // See https://cplusplus.github.io/LWG/lwg-defects.html#2767
594 struct Abstract { virtual void f() const = 0; };
595 struct Derived : public Abstract { void f() const {} };
596 struct F { bool operator()(Abstract&&) { return false; } };
597 {
598 Derived d;
599 Abstract &a = d;
600 bool b = std::not_fn(F{})(std::move(a));
601 assert(b);
602 }
603 }
604
main(int,char **)605 int main(int, char**)
606 {
607 constructor_tests();
608 return_type_tests();
609 other_callable_types_test();
610 throws_in_constructor_test();
611 call_operator_sfinae_test(); // somewhat of an extension
612 call_operator_forwarding_test();
613 call_operator_noexcept_test();
614 test_lwg2767();
615
616 return 0;
617 }
618