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 constexpr bool returns_true() { return true; } 27 28 template <class Ret = bool> 29 struct MoveOnlyCallable { 30 MoveOnlyCallable(MoveOnlyCallable const&) = delete; 31 constexpr MoveOnlyCallable(MoveOnlyCallable&& other) 32 : value(other.value) 33 { other.value = !other.value; } 34 35 template <class ...Args> 36 constexpr Ret operator()(Args&&...) { return Ret{value}; } 37 38 constexpr explicit MoveOnlyCallable(bool x) : value(x) {} 39 Ret value; 40 }; 41 42 template <class Ret = bool> 43 struct CopyCallable { 44 constexpr CopyCallable(CopyCallable const& other) 45 : value(other.value) {} 46 47 constexpr CopyCallable(CopyCallable&& other) 48 : value(other.value) { other.value = !other.value; } 49 50 template <class ...Args> 51 constexpr Ret operator()(Args&&...) { return Ret{value}; } 52 53 constexpr explicit CopyCallable(bool x) : value(x) {} 54 Ret value; 55 }; 56 57 58 template <class Ret = bool> 59 struct ConstCallable { 60 constexpr ConstCallable(ConstCallable const& other) 61 : value(other.value) {} 62 63 constexpr ConstCallable(ConstCallable&& other) 64 : value(other.value) { other.value = !other.value; } 65 66 template <class ...Args> 67 constexpr Ret operator()(Args&&...) const { return Ret{value}; } 68 69 constexpr explicit ConstCallable(bool x) : value(x) {} 70 Ret value; 71 }; 72 73 74 75 template <class Ret = bool> 76 struct NoExceptCallable { 77 constexpr NoExceptCallable(NoExceptCallable const& other) 78 : value(other.value) {} 79 80 template <class ...Args> 81 constexpr Ret operator()(Args&&...) noexcept { return Ret{value}; } 82 83 template <class ...Args> 84 constexpr Ret operator()(Args&&...) const noexcept { return Ret{value}; } 85 86 constexpr explicit NoExceptCallable(bool x) : value(x) {} 87 Ret value; 88 }; 89 90 struct CopyAssignableWrapper { 91 constexpr CopyAssignableWrapper(CopyAssignableWrapper const&) = default; 92 constexpr CopyAssignableWrapper(CopyAssignableWrapper&&) = default; 93 constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; 94 constexpr CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; 95 96 template <class ...Args> 97 constexpr bool operator()(Args&&...) { return value; } 98 99 constexpr explicit CopyAssignableWrapper(bool x) : value(x) {} 100 bool value; 101 }; 102 103 104 struct MoveAssignableWrapper { 105 constexpr MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; 106 constexpr MoveAssignableWrapper(MoveAssignableWrapper&&) = default; 107 constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; 108 constexpr MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; 109 110 template <class ...Args> 111 constexpr bool operator()(Args&&...) { return value; } 112 113 constexpr explicit MoveAssignableWrapper(bool x) : value(x) {} 114 bool value; 115 }; 116 117 struct MemFunCallable { 118 constexpr explicit MemFunCallable(bool x) : value(x) {} 119 120 constexpr bool return_value() const { return value; } 121 constexpr 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 struct State { 139 CallType last_call_type = CT_None; 140 TypeID const& (*last_call_args)() = nullptr; 141 142 template <class ...Args> 143 constexpr void set_call(CallType type) { 144 assert(last_call_type == CT_None); 145 assert(last_call_args == nullptr); 146 last_call_type = type; 147 last_call_args = &makeArgumentID<Args...>; 148 } 149 150 template <class ...Args> 151 constexpr bool check_call(CallType type) { 152 bool result = 153 last_call_type == type 154 && last_call_args 155 && *last_call_args == &makeArgumentID<Args...>; 156 last_call_type = CT_None; 157 last_call_args = nullptr; 158 return result; 159 } 160 }; 161 162 State *st_; 163 164 explicit constexpr ForwardingCallObject(State& st) : st_(&st) {} 165 166 template <class ...Args> 167 constexpr bool operator()(Args&&...) & { 168 st_->set_call<Args&&...>(CT_NonConst | CT_LValue); 169 return true; 170 } 171 172 template <class ...Args> 173 constexpr bool operator()(Args&&...) const & { 174 st_->set_call<Args&&...>(CT_Const | CT_LValue); 175 return true; 176 } 177 178 // Don't allow the call operator to be invoked as an rvalue. 179 template <class ...Args> 180 constexpr bool operator()(Args&&...) && { 181 st_->set_call<Args&&...>(CT_NonConst | CT_RValue); 182 return true; 183 } 184 185 template <class ...Args> 186 constexpr bool operator()(Args&&...) const && { 187 st_->set_call<Args&&...>(CT_Const | CT_RValue); 188 return true; 189 } 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 constexpr 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 constexpr explicit operator bool() const { return value; } 227 228 private: 229 friend struct MoveOnlyCallable<ExplicitBool>; 230 friend struct CopyCallable<ExplicitBool>; 231 232 constexpr explicit ExplicitBool(bool x) : value(x) {} 233 constexpr 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 constexpr 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 TEST_CONSTEXPR_CXX20 259 bool constructor_tests() 260 { 261 { 262 using T = MoveOnlyCallable<bool>; 263 T value(true); 264 using RetT = decltype(std::not_fn(std::move(value))); 265 static_assert(std::is_move_constructible<RetT>::value, ""); 266 static_assert(!std::is_copy_constructible<RetT>::value, ""); 267 static_assert(!std::is_move_assignable<RetT>::value, ""); 268 static_assert(!std::is_copy_assignable<RetT>::value, ""); 269 auto ret = std::not_fn(std::move(value)); 270 // test it was moved from 271 assert(value.value == false); 272 // test that ret() negates the original value 'true' 273 assert(ret() == false); 274 assert(ret(0, 0.0, "blah") == false); 275 // Move ret and test that it was moved from and that ret2 got the 276 // original value. 277 auto ret2 = std::move(ret); 278 assert(ret() == true); 279 assert(ret2() == false); 280 assert(ret2(42) == false); 281 } 282 { 283 using T = CopyCallable<bool>; 284 T value(false); 285 using RetT = decltype(std::not_fn(value)); 286 static_assert(std::is_move_constructible<RetT>::value, ""); 287 static_assert(std::is_copy_constructible<RetT>::value, ""); 288 static_assert(!std::is_move_assignable<RetT>::value, ""); 289 static_assert(!std::is_copy_assignable<RetT>::value, ""); 290 auto ret = std::not_fn(value); 291 // test that value is unchanged (copied not moved) 292 assert(value.value == false); 293 // test 'ret' has the original value 294 assert(ret() == true); 295 assert(ret(42, 100) == true); 296 // move from 'ret' and check that 'ret2' has the original value. 297 auto ret2 = std::move(ret); 298 assert(ret() == false); 299 assert(ret2() == true); 300 assert(ret2("abc") == true); 301 } 302 { 303 using T = CopyAssignableWrapper; 304 T value(true); 305 T value2(false); 306 using RetT = decltype(std::not_fn(value)); 307 static_assert(std::is_move_constructible<RetT>::value, ""); 308 static_assert(std::is_copy_constructible<RetT>::value, ""); 309 LIBCPP_STATIC_ASSERT(std::is_move_assignable<RetT>::value, ""); 310 LIBCPP_STATIC_ASSERT(std::is_copy_assignable<RetT>::value, ""); 311 auto ret = std::not_fn(value); 312 assert(ret() == false); 313 auto ret2 = std::not_fn(value2); 314 assert(ret2() == true); 315 #if defined(_LIBCPP_VERSION) 316 ret = ret2; 317 assert(ret() == true); 318 assert(ret2() == true); 319 #endif // _LIBCPP_VERSION 320 } 321 { 322 using T = MoveAssignableWrapper; 323 T value(true); 324 T value2(false); 325 using RetT = decltype(std::not_fn(std::move(value))); 326 static_assert(std::is_move_constructible<RetT>::value, ""); 327 static_assert(!std::is_copy_constructible<RetT>::value, ""); 328 LIBCPP_STATIC_ASSERT(std::is_move_assignable<RetT>::value, ""); 329 static_assert(!std::is_copy_assignable<RetT>::value, ""); 330 auto ret = std::not_fn(std::move(value)); 331 assert(ret() == false); 332 auto ret2 = std::not_fn(std::move(value2)); 333 assert(ret2() == true); 334 #if defined(_LIBCPP_VERSION) 335 ret = std::move(ret2); 336 assert(ret() == true); 337 #endif // _LIBCPP_VERSION 338 } 339 return true; 340 } 341 342 void return_type_tests() 343 { 344 using std::is_same; 345 { 346 using T = CopyCallable<bool>; 347 auto ret = std::not_fn(T{false}); 348 static_assert(is_same<decltype(ret()), bool>::value, ""); 349 static_assert(is_same<decltype(ret("abc")), bool>::value, ""); 350 assert(ret() == true); 351 } 352 { 353 using T = CopyCallable<ExplicitBool>; 354 auto ret = std::not_fn(T{true}); 355 static_assert(is_same<decltype(ret()), bool>::value, ""); 356 static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, ""); 357 assert(ret() == false); 358 } 359 { 360 using T = CopyCallable<EvilBool>; 361 auto ret = std::not_fn(T{false}); 362 static_assert(is_same<decltype(ret()), EvilBool>::value, ""); 363 EvilBool::bang_called = 0; 364 auto value_ret = ret(); 365 assert(EvilBool::bang_called == 1); 366 assert(value_ret.value == true); 367 ret(); 368 assert(EvilBool::bang_called == 2); 369 } 370 } 371 372 // Other tests only test using objects with call operators. Test various 373 // other callable types here. 374 TEST_CONSTEXPR_CXX20 375 bool other_callable_types_test() 376 { 377 { // test with function pointer 378 auto ret = std::not_fn(returns_true); 379 assert(ret() == false); 380 } 381 { // test with lambda 382 auto returns_value = [](bool value) { return value; }; 383 auto ret = std::not_fn(returns_value); 384 assert(ret(true) == false); 385 assert(ret(false) == true); 386 } 387 { // test with pointer to member function 388 MemFunCallable mt(true); 389 const MemFunCallable mf(false); 390 auto ret = std::not_fn(&MemFunCallable::return_value); 391 assert(ret(mt) == false); 392 assert(ret(mf) == true); 393 assert(ret(&mt) == false); 394 assert(ret(&mf) == true); 395 } 396 { // test with pointer to member function 397 MemFunCallable mt(true); 398 MemFunCallable mf(false); 399 auto ret = std::not_fn(&MemFunCallable::return_value_nc); 400 assert(ret(mt) == false); 401 assert(ret(mf) == true); 402 assert(ret(&mt) == false); 403 assert(ret(&mf) == true); 404 } 405 { // test with pointer to member data 406 MemFunCallable mt(true); 407 const MemFunCallable mf(false); 408 auto ret = std::not_fn(&MemFunCallable::value); 409 assert(ret(mt) == false); 410 assert(ret(mf) == true); 411 assert(ret(&mt) == false); 412 assert(ret(&mf) == true); 413 } 414 return true; 415 } 416 417 void throws_in_constructor_test() 418 { 419 #ifndef TEST_HAS_NO_EXCEPTIONS 420 struct ThrowsOnCopy { 421 ThrowsOnCopy(ThrowsOnCopy const&) { 422 throw 42; 423 } 424 ThrowsOnCopy() = default; 425 bool operator()() const { 426 assert(false); 427 #if defined(TEST_COMPILER_C1XX) 428 __assume(0); 429 #else 430 __builtin_unreachable(); 431 #endif 432 } 433 }; 434 { 435 ThrowsOnCopy cp; 436 try { 437 (void)std::not_fn(cp); 438 assert(false); 439 } catch (int const& value) { 440 assert(value == 42); 441 } 442 } 443 #endif 444 } 445 446 TEST_CONSTEXPR_CXX20 447 bool call_operator_sfinae_test() { 448 { // wrong number of arguments 449 using T = decltype(std::not_fn(returns_true)); 450 static_assert(std::is_invocable<T>::value, ""); // callable only with no args 451 static_assert(!std::is_invocable<T, bool>::value, ""); 452 } 453 { // violates const correctness (member function pointer) 454 using T = decltype(std::not_fn(&MemFunCallable::return_value_nc)); 455 static_assert(std::is_invocable<T, MemFunCallable&>::value, ""); 456 static_assert(!std::is_invocable<T, const MemFunCallable&>::value, ""); 457 } 458 { // violates const correctness (call object) 459 using Obj = CopyCallable<bool>; 460 using NCT = decltype(std::not_fn(Obj{true})); 461 using CT = const NCT; 462 static_assert(std::is_invocable<NCT>::value, ""); 463 static_assert(!std::is_invocable<CT>::value, ""); 464 } 465 { // returns bad type with no operator! 466 auto fn = [](auto x) { return x; }; 467 using T = decltype(std::not_fn(fn)); 468 static_assert(std::is_invocable<T, bool>::value, ""); 469 static_assert(!std::is_invocable<T, std::string>::value, ""); 470 } 471 return true; 472 } 473 474 TEST_CONSTEXPR_CXX20 475 bool call_operator_forwarding_test() 476 { 477 using Fn = ForwardingCallObject; 478 Fn::State st; 479 auto obj = std::not_fn(Fn{st}); 480 const auto& c_obj = obj; 481 { // test zero args 482 obj(); 483 assert(st.check_call<>(CT_NonConst | CT_LValue)); 484 std::move(obj)(); 485 assert(st.check_call<>(CT_NonConst | CT_RValue)); 486 c_obj(); 487 assert(st.check_call<>(CT_Const | CT_LValue)); 488 std::move(c_obj)(); 489 assert(st.check_call<>(CT_Const | CT_RValue)); 490 } 491 { // test value categories 492 int x = 42; 493 const int cx = 42; 494 obj(x); 495 assert(st.check_call<int&>(CT_NonConst | CT_LValue)); 496 obj(cx); 497 assert(st.check_call<const int&>(CT_NonConst | CT_LValue)); 498 obj(std::move(x)); 499 assert(st.check_call<int&&>(CT_NonConst | CT_LValue)); 500 obj(std::move(cx)); 501 assert(st.check_call<const int&&>(CT_NonConst | CT_LValue)); 502 obj(42); 503 assert(st.check_call<int&&>(CT_NonConst | CT_LValue)); 504 } 505 { // test value categories - rvalue 506 int x = 42; 507 const int cx = 42; 508 std::move(obj)(x); 509 assert(st.check_call<int&>(CT_NonConst | CT_RValue)); 510 std::move(obj)(cx); 511 assert(st.check_call<const int&>(CT_NonConst | CT_RValue)); 512 std::move(obj)(std::move(x)); 513 assert(st.check_call<int&&>(CT_NonConst | CT_RValue)); 514 std::move(obj)(std::move(cx)); 515 assert(st.check_call<const int&&>(CT_NonConst | CT_RValue)); 516 std::move(obj)(42); 517 assert(st.check_call<int&&>(CT_NonConst | CT_RValue)); 518 } 519 { // test value categories - const call 520 int x = 42; 521 const int cx = 42; 522 c_obj(x); 523 assert(st.check_call<int&>(CT_Const | CT_LValue)); 524 c_obj(cx); 525 assert(st.check_call<const int&>(CT_Const | CT_LValue)); 526 c_obj(std::move(x)); 527 assert(st.check_call<int&&>(CT_Const | CT_LValue)); 528 c_obj(std::move(cx)); 529 assert(st.check_call<const int&&>(CT_Const | CT_LValue)); 530 c_obj(42); 531 assert(st.check_call<int&&>(CT_Const | CT_LValue)); 532 } 533 { // test value categories - const call rvalue 534 int x = 42; 535 const int cx = 42; 536 std::move(c_obj)(x); 537 assert(st.check_call<int&>(CT_Const | CT_RValue)); 538 std::move(c_obj)(cx); 539 assert(st.check_call<const int&>(CT_Const | CT_RValue)); 540 std::move(c_obj)(std::move(x)); 541 assert(st.check_call<int&&>(CT_Const | CT_RValue)); 542 std::move(c_obj)(std::move(cx)); 543 assert(st.check_call<const int&&>(CT_Const | CT_RValue)); 544 std::move(c_obj)(42); 545 assert(st.check_call<int&&>(CT_Const | CT_RValue)); 546 } 547 { // test multi arg 548 using String = const char *; 549 const double y = 3.14; 550 String s = "abc"; 551 obj(42, std::move(y), s, String{"foo"}); 552 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_LValue))); 553 std::move(obj)(42, std::move(y), s, String{"foo"}); 554 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_RValue))); 555 c_obj(42, std::move(y), s, String{"foo"}); 556 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_LValue))); 557 std::move(c_obj)(42, std::move(y), s, String{"foo"}); 558 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_RValue))); 559 } 560 return true; 561 } 562 563 TEST_CONSTEXPR_CXX20 564 bool call_operator_noexcept_test() 565 { 566 { 567 using T = ConstCallable<bool>; 568 T value(true); 569 auto ret = std::not_fn(value); 570 static_assert(!noexcept(ret()), "call should not be noexcept"); 571 auto const& cret = ret; 572 static_assert(!noexcept(cret()), "call should not be noexcept"); 573 } 574 { 575 using T = NoExceptCallable<bool>; 576 T value(true); 577 auto ret = std::not_fn(value); 578 LIBCPP_STATIC_ASSERT(noexcept(!_VSTD::__invoke(value)), ""); 579 #if TEST_STD_VER > 14 580 static_assert(noexcept(!std::invoke(value)), ""); 581 #endif 582 static_assert(noexcept(ret()), "call should be noexcept"); 583 auto const& cret = ret; 584 static_assert(noexcept(cret()), "call should be noexcept"); 585 } 586 { 587 using T = NoExceptCallable<NoExceptEvilBool>; 588 T value(true); 589 auto ret = std::not_fn(value); 590 static_assert(noexcept(ret()), "call should not be noexcept"); 591 auto const& cret = ret; 592 static_assert(noexcept(cret()), "call should not be noexcept"); 593 } 594 { 595 using T = NoExceptCallable<EvilBool>; 596 T value(true); 597 auto ret = std::not_fn(value); 598 static_assert(!noexcept(ret()), "call should not be noexcept"); 599 auto const& cret = ret; 600 static_assert(!noexcept(cret()), "call should not be noexcept"); 601 } 602 return true; 603 } 604 605 TEST_CONSTEXPR_CXX20 606 bool test_lwg2767() { 607 // See https://cplusplus.github.io/LWG/lwg-defects.html#2767 608 struct Abstract { virtual void f() const = 0; }; 609 struct Derived : public Abstract { void f() const {} }; 610 struct F { constexpr bool operator()(Abstract&&) { return false; } }; 611 { 612 Derived d; 613 Abstract &a = d; 614 bool b = std::not_fn(F{})(std::move(a)); 615 assert(b); 616 } 617 return true; 618 } 619 620 int main(int, char**) 621 { 622 constructor_tests(); 623 return_type_tests(); 624 other_callable_types_test(); 625 throws_in_constructor_test(); 626 call_operator_sfinae_test(); // somewhat of an extension 627 call_operator_forwarding_test(); 628 call_operator_noexcept_test(); 629 test_lwg2767(); 630 631 #if TEST_STD_VER >= 20 632 static_assert(constructor_tests()); 633 static_assert(other_callable_types_test()); 634 static_assert(call_operator_sfinae_test()); // somewhat of an extension 635 static_assert(call_operator_forwarding_test()); 636 static_assert(call_operator_noexcept_test()); 637 static_assert(test_lwg2767()); 638 #endif 639 640 return 0; 641 } 642