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