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 #include "callable_types.h" 21 22 /////////////////////////////////////////////////////////////////////////////// 23 // BOOL TEST TYPES 24 /////////////////////////////////////////////////////////////////////////////// 25 26 struct EvilBool { 27 static int bang_called; 28 29 EvilBool(EvilBool const&) = default; 30 EvilBool(EvilBool&&) = default; 31 32 friend EvilBool operator!(EvilBool const& other) { 33 ++bang_called; 34 return EvilBool{!other.value}; 35 } 36 37 private: 38 friend struct MoveOnlyCallable<EvilBool>; 39 friend struct CopyCallable<EvilBool>; 40 friend struct NoExceptCallable<EvilBool>; 41 42 constexpr explicit EvilBool(bool x) : value(x) {} 43 EvilBool& operator=(EvilBool const& other) = default; 44 45 public: 46 bool value; 47 }; 48 49 int EvilBool::bang_called = 0; 50 51 struct ExplicitBool { 52 ExplicitBool(ExplicitBool const&) = default; 53 ExplicitBool(ExplicitBool&&) = default; 54 55 constexpr explicit operator bool() const { return value; } 56 57 private: 58 friend struct MoveOnlyCallable<ExplicitBool>; 59 friend struct CopyCallable<ExplicitBool>; 60 61 constexpr explicit ExplicitBool(bool x) : value(x) {} 62 constexpr ExplicitBool& operator=(bool x) { 63 value = x; 64 return *this; 65 } 66 67 bool value; 68 }; 69 70 71 struct NoExceptEvilBool { 72 NoExceptEvilBool(NoExceptEvilBool const&) = default; 73 NoExceptEvilBool(NoExceptEvilBool&&) = default; 74 NoExceptEvilBool& operator=(NoExceptEvilBool const& other) = default; 75 76 constexpr explicit NoExceptEvilBool(bool x) : value(x) {} 77 78 friend NoExceptEvilBool operator!(NoExceptEvilBool const& other) noexcept { 79 return NoExceptEvilBool{!other.value}; 80 } 81 82 bool value; 83 }; 84 85 86 87 TEST_CONSTEXPR_CXX20 88 bool constructor_tests() 89 { 90 { 91 using T = MoveOnlyCallable<bool>; 92 T value(true); 93 using RetT = decltype(std::not_fn(std::move(value))); 94 static_assert(std::is_move_constructible<RetT>::value, ""); 95 static_assert(!std::is_copy_constructible<RetT>::value, ""); 96 static_assert(!std::is_move_assignable<RetT>::value, ""); 97 static_assert(!std::is_copy_assignable<RetT>::value, ""); 98 auto ret = std::not_fn(std::move(value)); 99 // test it was moved from 100 assert(value.value == false); 101 // test that ret() negates the original value 'true' 102 assert(ret() == false); 103 assert(ret(0, 0.0, "blah") == false); 104 // Move ret and test that it was moved from and that ret2 got the 105 // original value. 106 auto ret2 = std::move(ret); 107 assert(ret() == true); 108 assert(ret2() == false); 109 assert(ret2(42) == false); 110 } 111 { 112 using T = CopyCallable<bool>; 113 T value(false); 114 using RetT = decltype(std::not_fn(value)); 115 static_assert(std::is_move_constructible<RetT>::value, ""); 116 static_assert(std::is_copy_constructible<RetT>::value, ""); 117 static_assert(!std::is_move_assignable<RetT>::value, ""); 118 static_assert(!std::is_copy_assignable<RetT>::value, ""); 119 auto ret = std::not_fn(value); 120 // test that value is unchanged (copied not moved) 121 assert(value.value == false); 122 // test 'ret' has the original value 123 assert(ret() == true); 124 assert(ret(42, 100) == true); 125 // move from 'ret' and check that 'ret2' has the original value. 126 auto ret2 = std::move(ret); 127 assert(ret() == false); 128 assert(ret2() == true); 129 assert(ret2("abc") == true); 130 // initialize not_fn with rvalue 131 auto ret3 = std::not_fn(std::move(value)); 132 assert(ret(0) == false); 133 assert(ret3(0) == true); 134 } 135 { 136 using T = CopyAssignableWrapper; 137 T value(true); 138 T value2(false); 139 using RetT = decltype(std::not_fn(value)); 140 static_assert(std::is_move_constructible<RetT>::value, ""); 141 static_assert(std::is_copy_constructible<RetT>::value, ""); 142 auto ret = std::not_fn(value); 143 assert(ret() == false); 144 auto ret2 = std::not_fn(value2); 145 assert(ret2() == true); 146 } 147 { 148 using T = MoveAssignableWrapper; 149 T value(true); 150 T value2(false); 151 using RetT = decltype(std::not_fn(std::move(value))); 152 static_assert(std::is_move_constructible<RetT>::value, ""); 153 static_assert(!std::is_copy_constructible<RetT>::value, ""); 154 static_assert(!std::is_copy_assignable<RetT>::value, ""); 155 auto ret = std::not_fn(std::move(value)); 156 assert(ret() == false); 157 auto ret2 = std::not_fn(std::move(value2)); 158 assert(ret2() == true); 159 } 160 return true; 161 } 162 163 void return_type_tests() 164 { 165 using std::is_same; 166 { 167 using T = CopyCallable<bool>; 168 auto ret = std::not_fn(T{false}); 169 static_assert(is_same<decltype(ret()), bool>::value, ""); 170 static_assert(is_same<decltype(ret("abc")), bool>::value, ""); 171 assert(ret() == true); 172 } 173 { 174 using T = CopyCallable<ExplicitBool>; 175 auto ret = std::not_fn(T{true}); 176 static_assert(is_same<decltype(ret()), bool>::value, ""); 177 static_assert(is_same<decltype(ret(std::string("abc"))), bool>::value, ""); 178 assert(ret() == false); 179 } 180 { 181 using T = CopyCallable<EvilBool>; 182 auto ret = std::not_fn(T{false}); 183 static_assert(is_same<decltype(ret()), EvilBool>::value, ""); 184 EvilBool::bang_called = 0; 185 auto value_ret = ret(); 186 assert(EvilBool::bang_called == 1); 187 assert(value_ret.value == true); 188 ret(); 189 assert(EvilBool::bang_called == 2); 190 } 191 } 192 193 // Other tests only test using objects with call operators. Test various 194 // other callable types here. 195 TEST_CONSTEXPR_CXX20 196 bool other_callable_types_test() 197 { 198 { // test with function pointer 199 auto ret = std::not_fn(returns_true); 200 assert(ret() == false); 201 } 202 { // test with lambda 203 auto returns_value = [](bool value) { return value; }; 204 auto ret = std::not_fn(returns_value); 205 assert(ret(true) == false); 206 assert(ret(false) == true); 207 } 208 { // test with pointer to member function 209 MemFunCallable mt(true); 210 const MemFunCallable mf(false); 211 auto ret = std::not_fn(&MemFunCallable::return_value); 212 assert(ret(mt) == false); 213 assert(ret(mf) == true); 214 assert(ret(&mt) == false); 215 assert(ret(&mf) == true); 216 } 217 { // test with pointer to member function 218 MemFunCallable mt(true); 219 MemFunCallable mf(false); 220 auto ret = std::not_fn(&MemFunCallable::return_value_nc); 221 assert(ret(mt) == false); 222 assert(ret(mf) == true); 223 assert(ret(&mt) == false); 224 assert(ret(&mf) == true); 225 } 226 { // test with pointer to member data 227 MemFunCallable mt(true); 228 const MemFunCallable mf(false); 229 auto ret = std::not_fn(&MemFunCallable::value); 230 assert(ret(mt) == false); 231 assert(ret(mf) == true); 232 assert(ret(&mt) == false); 233 assert(ret(&mf) == true); 234 } 235 return true; 236 } 237 238 void throws_in_constructor_test() 239 { 240 #ifndef TEST_HAS_NO_EXCEPTIONS 241 struct ThrowsOnCopy { 242 ThrowsOnCopy(ThrowsOnCopy const&) { 243 throw 42; 244 } 245 ThrowsOnCopy() = default; 246 bool operator()() const { 247 assert(false); 248 #ifdef TEST_COMPILER_MSVC 249 __assume(0); 250 #else 251 __builtin_unreachable(); 252 #endif 253 } 254 }; 255 { 256 ThrowsOnCopy cp; 257 try { 258 (void)std::not_fn(cp); 259 assert(false); 260 } catch (int const& value) { 261 assert(value == 42); 262 } 263 } 264 #endif 265 } 266 267 TEST_CONSTEXPR_CXX20 268 bool call_operator_sfinae_test() { 269 { // wrong number of arguments 270 using T = decltype(std::not_fn(returns_true)); 271 static_assert(std::is_invocable<T>::value, ""); // callable only with no args 272 static_assert(!std::is_invocable<T, bool>::value, ""); 273 } 274 { // violates const correctness (member function pointer) 275 using T = decltype(std::not_fn(&MemFunCallable::return_value_nc)); 276 static_assert(std::is_invocable<T, MemFunCallable&>::value, ""); 277 static_assert(!std::is_invocable<T, const MemFunCallable&>::value, ""); 278 } 279 { // violates const correctness (call object) 280 using Obj = CopyCallable<bool>; 281 using NCT = decltype(std::not_fn(Obj{true})); 282 using CT = const NCT; 283 static_assert(std::is_invocable<NCT>::value, ""); 284 static_assert(!std::is_invocable<CT>::value, ""); 285 } 286 { // returns bad type with no operator! 287 auto fn = [](auto x) { return x; }; 288 using T = decltype(std::not_fn(fn)); 289 static_assert(std::is_invocable<T, bool>::value, ""); 290 static_assert(!std::is_invocable<T, std::string>::value, ""); 291 } 292 return true; 293 } 294 295 TEST_CONSTEXPR_CXX20 296 bool call_operator_forwarding_test() 297 { 298 using Fn = ForwardingCallObject; 299 Fn::State st; 300 auto obj = std::not_fn(Fn{st}); 301 const auto& c_obj = obj; 302 { // test zero args 303 obj(); 304 assert(st.check_call<>(CT_NonConst | CT_LValue)); 305 std::move(obj)(); 306 assert(st.check_call<>(CT_NonConst | CT_RValue)); 307 c_obj(); 308 assert(st.check_call<>(CT_Const | CT_LValue)); 309 std::move(c_obj)(); 310 assert(st.check_call<>(CT_Const | CT_RValue)); 311 } 312 { // test value categories 313 int x = 42; 314 const int cx = 42; 315 obj(x); 316 assert(st.check_call<int&>(CT_NonConst | CT_LValue)); 317 obj(cx); 318 assert(st.check_call<const int&>(CT_NonConst | CT_LValue)); 319 obj(std::move(x)); 320 assert(st.check_call<int&&>(CT_NonConst | CT_LValue)); 321 obj(std::move(cx)); 322 assert(st.check_call<const int&&>(CT_NonConst | CT_LValue)); 323 obj(42); 324 assert(st.check_call<int&&>(CT_NonConst | CT_LValue)); 325 } 326 { // test value categories - rvalue 327 int x = 42; 328 const int cx = 42; 329 std::move(obj)(x); 330 assert(st.check_call<int&>(CT_NonConst | CT_RValue)); 331 std::move(obj)(cx); 332 assert(st.check_call<const int&>(CT_NonConst | CT_RValue)); 333 std::move(obj)(std::move(x)); 334 assert(st.check_call<int&&>(CT_NonConst | CT_RValue)); 335 std::move(obj)(std::move(cx)); 336 assert(st.check_call<const int&&>(CT_NonConst | CT_RValue)); 337 std::move(obj)(42); 338 assert(st.check_call<int&&>(CT_NonConst | CT_RValue)); 339 } 340 { // test value categories - const call 341 int x = 42; 342 const int cx = 42; 343 c_obj(x); 344 assert(st.check_call<int&>(CT_Const | CT_LValue)); 345 c_obj(cx); 346 assert(st.check_call<const int&>(CT_Const | CT_LValue)); 347 c_obj(std::move(x)); 348 assert(st.check_call<int&&>(CT_Const | CT_LValue)); 349 c_obj(std::move(cx)); 350 assert(st.check_call<const int&&>(CT_Const | CT_LValue)); 351 c_obj(42); 352 assert(st.check_call<int&&>(CT_Const | CT_LValue)); 353 } 354 { // test value categories - const call rvalue 355 int x = 42; 356 const int cx = 42; 357 std::move(c_obj)(x); 358 assert(st.check_call<int&>(CT_Const | CT_RValue)); 359 std::move(c_obj)(cx); 360 assert(st.check_call<const int&>(CT_Const | CT_RValue)); 361 std::move(c_obj)(std::move(x)); 362 assert(st.check_call<int&&>(CT_Const | CT_RValue)); 363 std::move(c_obj)(std::move(cx)); 364 assert(st.check_call<const int&&>(CT_Const | CT_RValue)); 365 std::move(c_obj)(42); 366 assert(st.check_call<int&&>(CT_Const | CT_RValue)); 367 } 368 { // test multi arg 369 using String = const char *; 370 const double y = 3.14; 371 String s = "abc"; 372 obj(42, std::move(y), s, String{"foo"}); 373 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_LValue))); 374 std::move(obj)(42, std::move(y), s, String{"foo"}); 375 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_NonConst | CT_RValue))); 376 c_obj(42, std::move(y), s, String{"foo"}); 377 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_LValue))); 378 std::move(c_obj)(42, std::move(y), s, String{"foo"}); 379 assert((st.check_call<int&&, const double&&, String&, String&&>(CT_Const | CT_RValue))); 380 } 381 return true; 382 } 383 384 TEST_CONSTEXPR_CXX20 385 bool call_operator_noexcept_test() 386 { 387 { 388 using T = ConstCallable<bool>; 389 T value(true); 390 auto ret = std::not_fn(value); 391 static_assert(!noexcept(ret()), "call should not be noexcept"); 392 auto const& cret = ret; 393 static_assert(!noexcept(cret()), "call should not be noexcept"); 394 } 395 { 396 using T = NoExceptCallable<bool>; 397 T value(true); 398 auto ret = std::not_fn(value); 399 LIBCPP_STATIC_ASSERT(noexcept(!_VSTD::__invoke(value)), ""); 400 #if TEST_STD_VER > 14 401 static_assert(noexcept(!std::invoke(value)), ""); 402 #endif 403 static_assert(noexcept(ret()), "call should be noexcept"); 404 auto const& cret = ret; 405 static_assert(noexcept(cret()), "call should be noexcept"); 406 } 407 { 408 using T = NoExceptCallable<NoExceptEvilBool>; 409 T value(true); 410 auto ret = std::not_fn(value); 411 static_assert(noexcept(ret()), "call should not be noexcept"); 412 auto const& cret = ret; 413 static_assert(noexcept(cret()), "call should not be noexcept"); 414 } 415 { 416 using T = NoExceptCallable<EvilBool>; 417 T value(true); 418 auto ret = std::not_fn(value); 419 static_assert(!noexcept(ret()), "call should not be noexcept"); 420 auto const& cret = ret; 421 static_assert(!noexcept(cret()), "call should not be noexcept"); 422 } 423 return true; 424 } 425 426 TEST_CONSTEXPR_CXX20 427 bool test_lwg2767() { 428 // See https://cplusplus.github.io/LWG/lwg-defects.html#2767 429 struct Abstract { virtual void f() const = 0; }; 430 struct Derived : public Abstract { void f() const {} }; 431 struct F { constexpr bool operator()(Abstract&&) { return false; } }; 432 { 433 Derived d; 434 Abstract &a = d; 435 bool b = std::not_fn(F{})(std::move(a)); 436 assert(b); 437 } 438 return true; 439 } 440 441 int main(int, char**) 442 { 443 constructor_tests(); 444 return_type_tests(); 445 other_callable_types_test(); 446 throws_in_constructor_test(); 447 call_operator_sfinae_test(); // somewhat of an extension 448 call_operator_forwarding_test(); 449 call_operator_noexcept_test(); 450 test_lwg2767(); 451 452 #if TEST_STD_VER >= 20 453 static_assert(constructor_tests()); 454 static_assert(other_callable_types_test()); 455 static_assert(call_operator_sfinae_test()); // somewhat of an extension 456 static_assert(call_operator_forwarding_test()); 457 static_assert(call_operator_noexcept_test()); 458 static_assert(test_lwg2767()); 459 #endif 460 461 return 0; 462 } 463