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 92 struct CopyAssignableWrapper { 93 CopyAssignableWrapper(CopyAssignableWrapper const&) = default; 94 CopyAssignableWrapper(CopyAssignableWrapper&&) = default; 95 CopyAssignableWrapper& operator=(CopyAssignableWrapper const&) = default; 96 CopyAssignableWrapper& operator=(CopyAssignableWrapper &&) = default; 97 98 template <class ...Args> 99 bool operator()(Args&&...) { return value; } 100 101 explicit CopyAssignableWrapper(bool x) : value(x) {} 102 bool value; 103 }; 104 105 106 struct MoveAssignableWrapper { 107 MoveAssignableWrapper(MoveAssignableWrapper const&) = delete; 108 MoveAssignableWrapper(MoveAssignableWrapper&&) = default; 109 MoveAssignableWrapper& operator=(MoveAssignableWrapper const&) = delete; 110 MoveAssignableWrapper& operator=(MoveAssignableWrapper &&) = default; 111 112 template <class ...Args> 113 bool operator()(Args&&...) { return value; } 114 115 explicit MoveAssignableWrapper(bool x) : value(x) {} 116 bool value; 117 }; 118 119 struct MemFunCallable { 120 explicit MemFunCallable(bool x) : value(x) {} 121 122 bool return_value() const { return value; } 123 bool return_value_nc() { return value; } 124 bool value; 125 }; 126 127 enum CallType { 128 CT_None, 129 CT_Const, 130 CT_NonConst 131 }; 132 133 struct ForwardingCallObject { 134 135 template <class ...Args> 136 bool operator()(Args&&... args) & { 137 set_call<Args&&...>(CT_NonConst); 138 return true; 139 } 140 141 template <class ...Args> 142 bool operator()(Args&&... args) const & { 143 set_call<Args&&...>(CT_Const); 144 return true; 145 } 146 147 // Don't allow the call operator to be invoked as an rvalue. 148 template <class ...Args> 149 bool operator()(Args&&... args) && = delete; 150 151 template <class ...Args> 152 bool operator()(Args&&... args) const && = delete; 153 154 template <class ...Args> 155 static void set_call(CallType type) { 156 assert(last_call_type == CT_None); 157 assert(last_call_args == nullptr); 158 last_call_type = type; 159 last_call_args = &makeArgumentID<Args...>(); 160 } 161 162 template <class ...Args> 163 static bool check_call(CallType type) { 164 bool result = 165 last_call_type == type 166 && last_call_args 167 && *last_call_args == makeArgumentID<Args...>(); 168 last_call_type = CT_None; 169 last_call_args = nullptr; 170 return result; 171 } 172 173 static CallType last_call_type; 174 static TypeID const* last_call_args; 175 }; 176 177 CallType ForwardingCallObject::last_call_type = CT_None; 178 TypeID const* ForwardingCallObject::last_call_args = nullptr; 179 180 181 182 /////////////////////////////////////////////////////////////////////////////// 183 // BOOL TEST TYPES 184 /////////////////////////////////////////////////////////////////////////////// 185 186 struct EvilBool { 187 static int bang_called; 188 189 EvilBool(EvilBool const&) = default; 190 EvilBool(EvilBool&&) = default; 191 192 friend EvilBool operator!(EvilBool const& other) { 193 ++bang_called; 194 return EvilBool{!other.value}; 195 } 196 197 private: 198 friend struct MoveOnlyCallable<EvilBool>; 199 friend struct CopyCallable<EvilBool>; 200 friend struct NoExceptCallable<EvilBool>; 201 202 explicit EvilBool(bool x) : value(x) {} 203 EvilBool& operator=(EvilBool const& other) = default; 204 205 public: 206 bool value; 207 }; 208 209 int EvilBool::bang_called = 0; 210 211 struct ExplicitBool { 212 ExplicitBool(ExplicitBool const&) = default; 213 ExplicitBool(ExplicitBool&&) = default; 214 215 explicit operator bool() const { return value; } 216 217 private: 218 friend struct MoveOnlyCallable<ExplicitBool>; 219 friend struct CopyCallable<ExplicitBool>; 220 221 explicit ExplicitBool(bool x) : value(x) {} 222 ExplicitBool& operator=(bool x) { 223 value = x; 224 return *this; 225 } 226 227 bool value; 228 }; 229 230 231 struct NoExceptEvilBool { 232 NoExceptEvilBool(NoExceptEvilBool const&) = default; 233 NoExceptEvilBool(NoExceptEvilBool&&) = default; 234 NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default; 235 236 explicit NoExceptEvilBool(bool x) : value(x) {} 237 238 friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept { 239 return NoExceptEvilBool{!other.value}; 240 } 241 242 bool value; 243 }; 244 245 246 247 void constructor_tests() 248 { 249 { 250 using T = MoveOnlyCallable<bool>; 251 T value(true); 252 using RetT = decltype(std::not_fn(std::move(value))); 253 static_assert(std::is_move_constructible<RetT>::value, ""); 254 static_assert(!std::is_copy_constructible<RetT>::value, ""); 255 static_assert(!std::is_move_assignable<RetT>::value, ""); 256 static_assert(!std::is_copy_assignable<RetT>::value, ""); 257 auto ret = std::not_fn(std::move(value)); 258 // test it was moved from 259 assert(value.value == false); 260 // test that ret() negates the original value 'true' 261 assert(ret() == false); 262 assert(ret(0, 0.0, "blah") == false); 263 // Move ret and test that it was moved from and that ret2 got the 264 // original value. 265 auto ret2 = std::move(ret); 266 assert(ret() == true); 267 assert(ret2() == false); 268 assert(ret2(42) == false); 269 } 270 { 271 using T = CopyCallable<bool>; 272 T value(false); 273 using RetT = decltype(std::not_fn(value)); 274 static_assert(std::is_move_constructible<RetT>::value, ""); 275 static_assert(std::is_copy_constructible<RetT>::value, ""); 276 static_assert(!std::is_move_assignable<RetT>::value, ""); 277 static_assert(!std::is_copy_assignable<RetT>::value, ""); 278 auto ret = std::not_fn(value); 279 // test that value is unchanged (copied not moved) 280 assert(value.value == false); 281 // test 'ret' has the original value 282 assert(ret() == true); 283 assert(ret(42, 100) == true); 284 // move from 'ret' and check that 'ret2' has the original value. 285 auto ret2 = std::move(ret); 286 assert(ret() == false); 287 assert(ret2() == true); 288 assert(ret2("abc") == true); 289 } 290 { 291 using T = CopyAssignableWrapper; 292 T value(true); 293 T value2(false); 294 using RetT = decltype(std::not_fn(value)); 295 static_assert(std::is_move_constructible<RetT>::value, ""); 296 static_assert(std::is_copy_constructible<RetT>::value, ""); 297 static_assert(std::is_move_assignable<RetT>::value, ""); 298 static_assert(std::is_copy_assignable<RetT>::value, ""); 299 auto ret = std::not_fn(value); 300 assert(ret() == false); 301 auto ret2 = std::not_fn(value2); 302 assert(ret2() == true); 303 ret = ret2; 304 assert(ret() == true); 305 assert(ret2() == true); 306 } 307 { 308 using T = MoveAssignableWrapper; 309 T value(true); 310 T value2(false); 311 using RetT = decltype(std::not_fn(std::move(value))); 312 static_assert(std::is_move_constructible<RetT>::value, ""); 313 static_assert(!std::is_copy_constructible<RetT>::value, ""); 314 static_assert(std::is_move_assignable<RetT>::value, ""); 315 static_assert(!std::is_copy_assignable<RetT>::value, ""); 316 auto ret = std::not_fn(std::move(value)); 317 assert(ret() == false); 318 auto ret2 = std::not_fn(std::move(value2)); 319 assert(ret2() == true); 320 ret = std::move(ret2); 321 assert(ret() == true); 322 } 323 } 324 325 void return_type_tests() 326 { 327 using std::is_same; 328 { 329 using T = CopyCallable<bool>; 330 auto ret = std::not_fn(T{false}); 331 static_assert(is_same<decltype(ret()), bool>::value, ""); 332 static_assert(is_same<decltype(ret("abc")), bool>::value, ""); 333 assert(ret() == true); 334 } 335 { 336 using T = CopyCallable<ExplicitBool>; 337 auto ret = std::not_fn(T{true}); 338 static_assert(is_same<decltype(ret()), bool>::value, ""); 339 static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, ""); 340 assert(ret() == false); 341 } 342 { 343 using T = CopyCallable<EvilBool>; 344 auto ret = std::not_fn(T{false}); 345 static_assert(is_same<decltype(ret()), EvilBool>::value, ""); 346 EvilBool::bang_called = 0; 347 auto value_ret = ret(); 348 assert(EvilBool::bang_called == 1); 349 assert(value_ret.value == true); 350 ret(); 351 assert(EvilBool::bang_called == 2); 352 } 353 } 354 355 // Other tests only test using objects with call operators. Test various 356 // other callable types here. 357 void other_callable_types_test() 358 { 359 { // test with function pointer 360 auto ret = std::not_fn(returns_true); 361 assert(ret() == false); 362 } 363 { // test with lambda 364 auto returns_value = [](bool value) { return value; }; 365 auto ret = std::not_fn(returns_value); 366 assert(ret(true) == false); 367 assert(ret(false) == true); 368 } 369 { // test with pointer to member function 370 MemFunCallable mt(true); 371 const MemFunCallable mf(false); 372 auto ret = std::not_fn(&MemFunCallable::return_value); 373 assert(ret(mt) == false); 374 assert(ret(mf) == true); 375 assert(ret(&mt) == false); 376 assert(ret(&mf) == true); 377 } 378 { // test with pointer to member function 379 MemFunCallable mt(true); 380 MemFunCallable mf(false); 381 auto ret = std::not_fn(&MemFunCallable::return_value_nc); 382 assert(ret(mt) == false); 383 assert(ret(mf) == true); 384 assert(ret(&mt) == false); 385 assert(ret(&mf) == true); 386 } 387 { // test with pointer to member data 388 MemFunCallable mt(true); 389 const MemFunCallable mf(false); 390 auto ret = std::not_fn(&MemFunCallable::value); 391 assert(ret(mt) == false); 392 assert(ret(mf) == true); 393 assert(ret(&mt) == false); 394 assert(ret(&mf) == true); 395 } 396 } 397 398 void throws_in_constructor_test() 399 { 400 #ifndef TEST_HAS_NO_EXCEPTIONS 401 struct ThrowsOnCopy { 402 ThrowsOnCopy(ThrowsOnCopy const&) { 403 throw 42; 404 } 405 ThrowsOnCopy() = default; 406 bool operator()() const { assert(false); } 407 }; 408 { 409 ThrowsOnCopy cp; 410 try { 411 std::not_fn(cp); 412 assert(false); 413 } catch (int const& value) { 414 assert(value == 42); 415 } 416 } 417 #endif 418 } 419 420 void call_operator_sfinae_test() { 421 { // wrong number of arguments 422 using T = decltype(std::not_fn(returns_true)); 423 static_assert(std::is_callable<T()>::value, ""); // callable only with no args 424 static_assert(!std::is_callable<T(bool)>::value, ""); 425 } 426 { // violates const correctness (member function pointer) 427 using T = decltype(std::not_fn(&MemFunCallable::return_value_nc)); 428 static_assert(std::is_callable<T(MemFunCallable&)>::value, ""); 429 static_assert(!std::is_callable<T(const MemFunCallable&)>::value, ""); 430 } 431 { // violates const correctness (call object) 432 using Obj = CopyCallable<bool>; 433 using NCT = decltype(std::not_fn(Obj{true})); 434 using CT = const NCT; 435 static_assert(std::is_callable<NCT()>::value, ""); 436 static_assert(!std::is_callable<CT()>::value, ""); 437 } 438 { // returns bad type with no operator! 439 auto fn = [](auto x) { return x; }; 440 using T = decltype(std::not_fn(fn)); 441 static_assert(std::is_callable<T(bool)>::value, ""); 442 static_assert(!std::is_callable<T(std::string)>::value, ""); 443 } 444 } 445 446 void call_operator_forwarding_test() 447 { 448 using Fn = ForwardingCallObject; 449 auto obj = std::not_fn(Fn{}); 450 const auto& c_obj = obj; 451 { // test zero args 452 obj(); 453 assert(Fn::check_call<>(CT_NonConst)); 454 c_obj(); 455 assert(Fn::check_call<>(CT_Const)); 456 } 457 { // test value categories 458 int x = 42; 459 const int cx = 42; 460 obj(x); 461 assert(Fn::check_call<int&>(CT_NonConst)); 462 obj(cx); 463 assert(Fn::check_call<const int&>(CT_NonConst)); 464 obj(std::move(x)); 465 assert(Fn::check_call<int&&>(CT_NonConst)); 466 obj(std::move(cx)); 467 assert(Fn::check_call<const int&&>(CT_NonConst)); 468 obj(42); 469 assert(Fn::check_call<int&&>(CT_NonConst)); 470 } 471 { // test value categories - const call 472 int x = 42; 473 const int cx = 42; 474 c_obj(x); 475 assert(Fn::check_call<int&>(CT_Const)); 476 c_obj(cx); 477 assert(Fn::check_call<const int&>(CT_Const)); 478 c_obj(std::move(x)); 479 assert(Fn::check_call<int&&>(CT_Const)); 480 c_obj(std::move(cx)); 481 assert(Fn::check_call<const int&&>(CT_Const)); 482 c_obj(42); 483 assert(Fn::check_call<int&&>(CT_Const)); 484 } 485 { // test multi arg 486 int x = 42; 487 const double y = 3.14; 488 std::string s = "abc"; 489 obj(42, std::move(y), s, std::string{"foo"}); 490 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_NonConst); 491 c_obj(42, std::move(y), s, std::string{"foo"}); 492 Fn::check_call<int&&, const double&&, std::string&, std::string&&>(CT_Const); 493 } 494 { // call as rvalue test. This should not invoke the functor as an rvalue. 495 std::move(obj)(); 496 assert(Fn::check_call<>(CT_NonConst)); 497 std::move(c_obj)(); 498 assert(Fn::check_call<>(CT_Const)); 499 } 500 } 501 502 void call_operator_noexcept_test() 503 { 504 { 505 using T = ConstCallable<bool>; 506 T value(true); 507 auto ret = std::not_fn(value); 508 static_assert(!noexcept(ret()), "call should not be noexcept"); 509 auto const& cret = ret; 510 static_assert(!noexcept(cret()), "call should not be noexcept"); 511 } 512 { 513 using T = NoExceptCallable<bool>; 514 T value(true); 515 auto ret = std::not_fn(value); 516 static_assert(noexcept(!_VSTD::__invoke(value)), ""); 517 static_assert(noexcept(ret()), "call should be noexcept"); 518 auto const& cret = ret; 519 static_assert(noexcept(cret()), "call should be noexcept"); 520 } 521 { 522 using T = NoExceptCallable<NoExceptEvilBool>; 523 T value(true); 524 auto ret = std::not_fn(value); 525 static_assert(noexcept(ret()), "call should not be noexcept"); 526 auto const& cret = ret; 527 static_assert(noexcept(cret()), "call should not be noexcept"); 528 } 529 { 530 using T = NoExceptCallable<EvilBool>; 531 T value(true); 532 auto ret = std::not_fn(value); 533 static_assert(!noexcept(ret()), "call should not be noexcept"); 534 auto const& cret = ret; 535 static_assert(!noexcept(cret()), "call should not be noexcept"); 536 } 537 } 538 539 int main() 540 { 541 constructor_tests(); 542 return_type_tests(); 543 other_callable_types_test(); 544 throws_in_constructor_test(); 545 call_operator_sfinae_test(); // somewhat of an extension 546 call_operator_forwarding_test(); 547 call_operator_noexcept_test(); 548 } 549