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 27 bool returns_true() { return true; } 28 29 template <class Ret = bool> 30 struct MoveOnlyCallable { 31 MoveOnlyCallable(MoveOnlyCallable const&) = delete; 32 MoveOnlyCallable(MoveOnlyCallable&& other) 33 : value(other.value) 34 { other.value = !other.value; } 35 36 template <class ...Args> 37 Ret operator()(Args&&...) { return Ret{value}; } 38 39 explicit MoveOnlyCallable(bool x) : value(x) {} 40 Ret value; 41 }; 42 43 template <class Ret = bool> 44 struct CopyCallable { 45 CopyCallable(CopyCallable const& other) 46 : value(other.value) {} 47 48 CopyCallable(CopyCallable&& other) 49 : value(other.value) { other.value = !other.value; } 50 51 template <class ...Args> 52 Ret operator()(Args&&...) { return Ret{value}; } 53 54 explicit CopyCallable(bool x) : value(x) {} 55 Ret value; 56 }; 57 58 59 template <class Ret = bool> 60 struct ConstCallable { 61 ConstCallable(ConstCallable const& other) 62 : value(other.value) {} 63 64 ConstCallable(ConstCallable&& other) 65 : value(other.value) { other.value = !other.value; } 66 67 template <class ...Args> 68 Ret operator()(Args&&...) const { return Ret{value}; } 69 70 explicit ConstCallable(bool x) : value(x) {} 71 Ret value; 72 }; 73 74 75 76 template <class Ret = bool> 77 struct NoExceptCallable { 78 NoExceptCallable(NoExceptCallable const& other) 79 : value(other.value) {} 80 81 template <class ...Args> 82 Ret operator()(Args&&...) noexcept { return Ret{value}; } 83 84 template <class ...Args> 85 Ret operator()(Args&&...) const noexcept { return Ret{value}; } 86 87 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> 98 bool operator()(Args&&...) { return value; } 99 100 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> 112 bool operator()(Args&&...) { return value; } 113 114 explicit MoveAssignableWrapper(bool x) : value(x) {} 115 bool value; 116 }; 117 118 struct MemFunCallable { 119 explicit MemFunCallable(bool x) : value(x) {} 120 121 bool return_value() const { return value; } 122 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 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> 141 bool operator()(Args&&...) & { 142 set_call<Args&&...>(CT_NonConst | CT_LValue); 143 return true; 144 } 145 146 template <class ...Args> 147 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> 154 bool operator()(Args&&...) && { 155 set_call<Args&&...>(CT_NonConst | CT_RValue); 156 return true; 157 } 158 159 template <class ...Args> 160 bool operator()(Args&&...) const && { 161 set_call<Args&&...>(CT_Const | CT_RValue); 162 return true; 163 } 164 165 template <class ...Args> 166 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> 174 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 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 213 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 226 explicit operator bool() const { return value; } 227 228 private: 229 friend struct MoveOnlyCallable<ExplicitBool>; 230 friend struct CopyCallable<ExplicitBool>; 231 232 explicit ExplicitBool(bool x) : value(x) {} 233 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 247 explicit NoExceptEvilBool(bool x) : value(x) {} 248 249 friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept { 250 return NoExceptEvilBool{!other.value}; 251 } 252 253 bool value; 254 }; 255 256 257 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 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. 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 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 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 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 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 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 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