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