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 static_assert(std::is_move_assignable<RetT>::value, ""); 309 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 ret = ret2; 315 assert(ret() == true); 316 assert(ret2() == true); 317 } 318 { 319 using T = MoveAssignableWrapper; 320 T value(true); 321 T value2(false); 322 using RetT = decltype(std::not_fn(std::move(value))); 323 static_assert(std::is_move_constructible<RetT>::value, ""); 324 static_assert(!std::is_copy_constructible<RetT>::value, ""); 325 static_assert(std::is_move_assignable<RetT>::value, ""); 326 static_assert(!std::is_copy_assignable<RetT>::value, ""); 327 auto ret = std::not_fn(std::move(value)); 328 assert(ret() == false); 329 auto ret2 = std::not_fn(std::move(value2)); 330 assert(ret2() == true); 331 ret = std::move(ret2); 332 assert(ret() == true); 333 } 334 } 335 336 void return_type_tests() 337 { 338 using std::is_same; 339 { 340 using T = CopyCallable<bool>; 341 auto ret = std::not_fn(T{false}); 342 static_assert(is_same<decltype(ret()), bool>::value, ""); 343 static_assert(is_same<decltype(ret("abc")), bool>::value, ""); 344 assert(ret() == true); 345 } 346 { 347 using T = CopyCallable<ExplicitBool>; 348 auto ret = std::not_fn(T{true}); 349 static_assert(is_same<decltype(ret()), bool>::value, ""); 350 static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, ""); 351 assert(ret() == false); 352 } 353 { 354 using T = CopyCallable<EvilBool>; 355 auto ret = std::not_fn(T{false}); 356 static_assert(is_same<decltype(ret()), EvilBool>::value, ""); 357 EvilBool::bang_called = 0; 358 auto value_ret = ret(); 359 assert(EvilBool::bang_called == 1); 360 assert(value_ret.value == true); 361 ret(); 362 assert(EvilBool::bang_called == 2); 363 } 364 } 365 366 // Other tests only test using objects with call operators. Test various 367 // other callable types here. 368 void other_callable_types_test() 369 { 370 { // test with function pointer 371 auto ret = std::not_fn(returns_true); 372 assert(ret() == false); 373 } 374 { // test with lambda 375 auto returns_value = [](bool value) { return value; }; 376 auto ret = std::not_fn(returns_value); 377 assert(ret(true) == false); 378 assert(ret(false) == true); 379 } 380 { // test with pointer to member function 381 MemFunCallable mt(true); 382 const MemFunCallable mf(false); 383 auto ret = std::not_fn(&MemFunCallable::return_value); 384 assert(ret(mt) == false); 385 assert(ret(mf) == true); 386 assert(ret(&mt) == false); 387 assert(ret(&mf) == true); 388 } 389 { // test with pointer to member function 390 MemFunCallable mt(true); 391 MemFunCallable mf(false); 392 auto ret = std::not_fn(&MemFunCallable::return_value_nc); 393 assert(ret(mt) == false); 394 assert(ret(mf) == true); 395 assert(ret(&mt) == false); 396 assert(ret(&mf) == true); 397 } 398 { // test with pointer to member data 399 MemFunCallable mt(true); 400 const MemFunCallable mf(false); 401 auto ret = std::not_fn(&MemFunCallable::value); 402 assert(ret(mt) == false); 403 assert(ret(mf) == true); 404 assert(ret(&mt) == false); 405 assert(ret(&mf) == true); 406 } 407 } 408 409 void throws_in_constructor_test() 410 { 411 #ifndef TEST_HAS_NO_EXCEPTIONS 412 struct ThrowsOnCopy { 413 ThrowsOnCopy(ThrowsOnCopy const&) { 414 throw 42; 415 } 416 ThrowsOnCopy() = default; 417 bool operator()() const { 418 assert(false); 419 #if defined(_LIBCPP_MSVC) 420 __assume(0); 421 #else 422 __builtin_unreachable(); 423 #endif 424 } 425 }; 426 { 427 ThrowsOnCopy cp; 428 try { 429 std::not_fn(cp); 430 assert(false); 431 } catch (int const& value) { 432 assert(value == 42); 433 } 434 } 435 #endif 436 } 437 438 void call_operator_sfinae_test() { 439 { // wrong number of arguments 440 using T = decltype(std::not_fn(returns_true)); 441 static_assert(std::is_callable<T()>::value, ""); // callable only with no args 442 static_assert(!std::is_callable<T(bool)>::value, ""); 443 } 444 { // violates const correctness (member function pointer) 445 using T = decltype(std::not_fn(&MemFunCallable::return_value_nc)); 446 static_assert(std::is_callable<T(MemFunCallable&)>::value, ""); 447 static_assert(!std::is_callable<T(const MemFunCallable&)>::value, ""); 448 } 449 { // violates const correctness (call object) 450 using Obj = CopyCallable<bool>; 451 using NCT = decltype(std::not_fn(Obj{true})); 452 using CT = const NCT; 453 static_assert(std::is_callable<NCT()>::value, ""); 454 static_assert(!std::is_callable<CT()>::value, ""); 455 } 456 { // returns bad type with no operator! 457 auto fn = [](auto x) { return x; }; 458 using T = decltype(std::not_fn(fn)); 459 static_assert(std::is_callable<T(bool)>::value, ""); 460 static_assert(!std::is_callable<T(std::string)>::value, ""); 461 } 462 } 463 464 void call_operator_forwarding_test() 465 { 466 using Fn = ForwardingCallObject; 467 auto obj = std::not_fn(Fn{}); 468 const auto& c_obj = obj; 469 { // test zero args 470 obj(); 471 assert(Fn::check_call<>(CT_NonConst | CT_LValue)); 472 std::move(obj)(); 473 assert(Fn::check_call<>(CT_NonConst | CT_RValue)); 474 c_obj(); 475 assert(Fn::check_call<>(CT_Const | CT_LValue)); 476 std::move(c_obj)(); 477 assert(Fn::check_call<>(CT_Const | CT_RValue)); 478 } 479 { // test value categories 480 int x = 42; 481 const int cx = 42; 482 obj(x); 483 assert(Fn::check_call<int&>(CT_NonConst | CT_LValue)); 484 obj(cx); 485 assert(Fn::check_call<const int&>(CT_NonConst | CT_LValue)); 486 obj(std::move(x)); 487 assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue)); 488 obj(std::move(cx)); 489 assert(Fn::check_call<const int&&>(CT_NonConst | CT_LValue)); 490 obj(42); 491 assert(Fn::check_call<int&&>(CT_NonConst | CT_LValue)); 492 } 493 { // test value categories - rvalue 494 int x = 42; 495 const int cx = 42; 496 std::move(obj)(x); 497 assert(Fn::check_call<int&>(CT_NonConst | CT_RValue)); 498 std::move(obj)(cx); 499 assert(Fn::check_call<const int&>(CT_NonConst | CT_RValue)); 500 std::move(obj)(std::move(x)); 501 assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue)); 502 std::move(obj)(std::move(cx)); 503 assert(Fn::check_call<const int&&>(CT_NonConst | CT_RValue)); 504 std::move(obj)(42); 505 assert(Fn::check_call<int&&>(CT_NonConst | CT_RValue)); 506 } 507 { // test value categories - const call 508 int x = 42; 509 const int cx = 42; 510 c_obj(x); 511 assert(Fn::check_call<int&>(CT_Const | CT_LValue)); 512 c_obj(cx); 513 assert(Fn::check_call<const int&>(CT_Const | CT_LValue)); 514 c_obj(std::move(x)); 515 assert(Fn::check_call<int&&>(CT_Const | CT_LValue)); 516 c_obj(std::move(cx)); 517 assert(Fn::check_call<const int&&>(CT_Const | CT_LValue)); 518 c_obj(42); 519 assert(Fn::check_call<int&&>(CT_Const | CT_LValue)); 520 } 521 { // test value categories - const call rvalue 522 int x = 42; 523 const int cx = 42; 524 std::move(c_obj)(x); 525 assert(Fn::check_call<int&>(CT_Const | CT_RValue)); 526 std::move(c_obj)(cx); 527 assert(Fn::check_call<const int&>(CT_Const | CT_RValue)); 528 std::move(c_obj)(std::move(x)); 529 assert(Fn::check_call<int&&>(CT_Const | CT_RValue)); 530 std::move(c_obj)(std::move(cx)); 531 assert(Fn::check_call<const int&&>(CT_Const | CT_RValue)); 532 std::move(c_obj)(42); 533 assert(Fn::check_call<int&&>(CT_Const | CT_RValue)); 534 } 535 { // test multi arg 536 const double y = 3.14; 537 std::string s = "abc"; 538 obj(42, std::move(y), s, std::string{"foo"}); 539 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_LValue); 540 std::move(obj)(42, std::move(y), s, std::string{"foo"}); 541 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst | CT_RValue); 542 c_obj(42, std::move(y), s, std::string{"foo"}); 543 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_LValue); 544 std::move(c_obj)(42, std::move(y), s, std::string{"foo"}); 545 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const | CT_RValue); 546 } 547 } 548 549 void call_operator_noexcept_test() 550 { 551 { 552 using T = ConstCallable<bool>; 553 T value(true); 554 auto ret = std::not_fn(value); 555 static_assert(!noexcept(ret()), "call should not be noexcept"); 556 auto const& cret = ret; 557 static_assert(!noexcept(cret()), "call should not be noexcept"); 558 } 559 { 560 using T = NoExceptCallable<bool>; 561 T value(true); 562 auto ret = std::not_fn(value); 563 LIBCPP_STATIC_ASSERT(noexcept(!_VSTD::__invoke(value)), ""); 564 #if TEST_STD_VER > 14 565 static_assert(noexcept(!std::invoke(value)), ""); 566 #endif 567 static_assert(noexcept(ret()), "call should be noexcept"); 568 auto const& cret = ret; 569 static_assert(noexcept(cret()), "call should be noexcept"); 570 } 571 { 572 using T = NoExceptCallable<NoExceptEvilBool>; 573 T value(true); 574 auto ret = std::not_fn(value); 575 static_assert(noexcept(ret()), "call should not be noexcept"); 576 auto const& cret = ret; 577 static_assert(noexcept(cret()), "call should not be noexcept"); 578 } 579 { 580 using T = NoExceptCallable<EvilBool>; 581 T value(true); 582 auto ret = std::not_fn(value); 583 static_assert(!noexcept(ret()), "call should not be noexcept"); 584 auto const& cret = ret; 585 static_assert(!noexcept(cret()), "call should not be noexcept"); 586 } 587 } 588 589 void test_lwg2767() { 590 // See http://wg21.link/LWG2767 591 struct Abstract { virtual void f() const = 0; }; 592 struct Derived : public Abstract { void f() const {} }; 593 struct F { bool operator()(Abstract&&) { return false; } }; 594 { 595 Derived d; 596 Abstract &a = d; 597 bool b = std::not_fn(F{})(std::move(a)); 598 assert(b); 599 } 600 } 601 602 int main() 603 { 604 constructor_tests(); 605 return_type_tests(); 606 other_callable_types_test(); 607 throws_in_constructor_test(); 608 call_operator_sfinae_test(); // somewhat of an extension 609 call_operator_forwarding_test(); 610 call_operator_noexcept_test(); 611 test_lwg2767(); 612 } 613