| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
| 8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
| 10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 344 private: | 344 private: |
| 345 MoveOnly(const MoveOnly&) = delete; | 345 MoveOnly(const MoveOnly&) = delete; |
| 346 MoveOnly& operator=(const MoveOnly&) = delete; | 346 MoveOnly& operator=(const MoveOnly&) = delete; |
| 347 | 347 |
| 348 // Disable move-assignment, since it isn't used within bind(). | 348 // Disable move-assignment, since it isn't used within bind(). |
| 349 MoveOnly& operator=(MoveOnly&&) = delete; | 349 MoveOnly& operator=(MoveOnly&&) = delete; |
| 350 | 350 |
| 351 int m_value; | 351 int m_value; |
| 352 }; | 352 }; |
| 353 | 353 |
| 354 int singleMoveOnly(MoveOnly& moveOnly) | 354 int singleMoveOnlyByLvalueReference(MoveOnly& moveOnly) |
| 355 { | 355 { |
| 356 int value = moveOnly.value(); | 356 int value = moveOnly.value(); |
| 357 // If you ever want to move out a bound parameter, that's possible by moving
the non-const lvalue reference. | 357 // If you ever want to move out a bound parameter, that's possible by moving
the non-const lvalue reference. |
| 358 MoveOnly(std::move(moveOnly)); | 358 MoveOnly(std::move(moveOnly)); |
| 359 return value; | 359 return value; |
| 360 } | 360 } |
| 361 | 361 |
| 362 int tripleMoveOnlys(MoveOnly& first, MoveOnly& second, MoveOnly& third) | 362 int tripleMoveOnlysByLvalueReferences(MoveOnly& first, MoveOnly& second, MoveOnl
y& third) |
| 363 { | 363 { |
| 364 int value = first.value() + second.value() + third.value(); | 364 int value = first.value() + second.value() + third.value(); |
| 365 MoveOnly(std::move(first)); | 365 MoveOnly(std::move(first)); |
| 366 MoveOnly(std::move(second)); | 366 MoveOnly(std::move(second)); |
| 367 MoveOnly(std::move(third)); | 367 MoveOnly(std::move(third)); |
| 368 return value; | 368 return value; |
| 369 } | 369 } |
| 370 | 370 |
| 371 TEST(FunctionalTest, BindMoveOnlyObjects) | 371 TEST(FunctionalTest, BindMoveOnlyObjects) |
| 372 { | 372 { |
| 373 MoveOnly one(1); | 373 MoveOnly one(1); |
| 374 OwnPtr<Function<int()>> bound = bind(singleMoveOnly, std::move(one)); | 374 OwnPtr<Function<int()>> bound = bind(singleMoveOnlyByLvalueReference, std::m
ove(one)); |
| 375 EXPECT_EQ(0, one.value()); // Should be moved away. | 375 EXPECT_EQ(0, one.value()); // Should be moved away. |
| 376 EXPECT_EQ(1, (*bound)()); | 376 EXPECT_EQ(1, (*bound)()); |
| 377 EXPECT_EQ(0, (*bound)()); // The stored value must be cleared in the first f
unction call. | 377 EXPECT_EQ(0, (*bound)()); // The stored value must be cleared in the first f
unction call. |
| 378 | 378 |
| 379 bound = bind(tripleMoveOnlys, MoveOnly(1), MoveOnly(2), MoveOnly(3)); | 379 bound = bind(tripleMoveOnlysByLvalueReferences, MoveOnly(1), MoveOnly(2), Mo
veOnly(3)); |
| 380 EXPECT_EQ(6, (*bound)()); | 380 EXPECT_EQ(6, (*bound)()); |
| 381 EXPECT_EQ(0, (*bound)()); | 381 EXPECT_EQ(0, (*bound)()); |
| 382 } | 382 } |
| 383 | 383 |
| 384 class CountCopy { | 384 class CountCopy { |
| 385 public: | 385 public: |
| 386 CountCopy() : m_copies(0) { } | 386 CountCopy() : m_copies(0) { } |
| 387 CountCopy(const CountCopy& other) : m_copies(other.m_copies + 1) { } | 387 CountCopy(const CountCopy& other) : m_copies(other.m_copies + 1) { } |
| 388 | 388 |
| 389 int copies() const { return m_copies; } | 389 int copies() const { return m_copies; } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 415 bound = bind(takeCountCopyAsConstReference, CountCopy()); // Rvalue. | 415 bound = bind(takeCountCopyAsConstReference, CountCopy()); // Rvalue. |
| 416 EXPECT_EQ(2, (*bound)()); | 416 EXPECT_EQ(2, (*bound)()); |
| 417 | 417 |
| 418 bound = bind(takeCountCopyAsValue, lvalue); | 418 bound = bind(takeCountCopyAsValue, lvalue); |
| 419 EXPECT_EQ(3, (*bound)()); // wrapping, unwrapping and copying in the final f
unction argument. | 419 EXPECT_EQ(3, (*bound)()); // wrapping, unwrapping and copying in the final f
unction argument. |
| 420 | 420 |
| 421 bound = bind(takeCountCopyAsValue, CountCopy()); | 421 bound = bind(takeCountCopyAsValue, CountCopy()); |
| 422 EXPECT_EQ(3, (*bound)()); | 422 EXPECT_EQ(3, (*bound)()); |
| 423 } | 423 } |
| 424 | 424 |
| 425 int singleMoveOnlyByRvalueReference(MoveOnly&& moveOnly) |
| 426 { |
| 427 int value = moveOnly.value(); |
| 428 MoveOnly(std::move(moveOnly)); |
| 429 return value; |
| 430 } |
| 431 |
| 432 int tripleMoveOnlysByRvalueReferences(MoveOnly&& first, MoveOnly&& second, MoveO
nly&& third) |
| 433 { |
| 434 int value = first.value() + second.value() + third.value(); |
| 435 MoveOnly(std::move(first)); |
| 436 MoveOnly(std::move(second)); |
| 437 MoveOnly(std::move(third)); |
| 438 return value; |
| 439 } |
| 440 |
| 441 int singleMoveOnlyByValue(MoveOnly moveOnly) |
| 442 { |
| 443 return moveOnly.value(); |
| 444 } |
| 445 |
| 446 int tripleMoveOnlysByValues(MoveOnly first, MoveOnly second, MoveOnly third) |
| 447 { |
| 448 return first.value() + second.value() + third.value(); |
| 449 } |
| 450 |
| 451 TEST(FunctionalTest, MoveUnboundArgumentsByRvalueReference) |
| 452 { |
| 453 OwnPtr<Function<int(MoveOnly&&)>> boundSingle = bind<MoveOnly&&>(singleMoveO
nlyByRvalueReference); |
| 454 EXPECT_EQ(1, (*boundSingle)(MoveOnly(1))); |
| 455 EXPECT_EQ(42, (*boundSingle)(MoveOnly(42))); |
| 456 |
| 457 OwnPtr<Function<int(MoveOnly&&, MoveOnly&&, MoveOnly&&)>> boundTriple = bind
<MoveOnly&&, MoveOnly&&, MoveOnly&&>(tripleMoveOnlysByRvalueReferences); |
| 458 EXPECT_EQ(6, (*boundTriple)(MoveOnly(1), MoveOnly(2), MoveOnly(3))); |
| 459 EXPECT_EQ(666, (*boundTriple)(MoveOnly(111), MoveOnly(222), MoveOnly(333))); |
| 460 |
| 461 OwnPtr<Function<int(MoveOnly)>> boundSingleByValue = bind<MoveOnly>(singleMo
veOnlyByValue); |
| 462 EXPECT_EQ(1, (*boundSingleByValue)(MoveOnly(1))); |
| 463 |
| 464 OwnPtr<Function<int(MoveOnly, MoveOnly, MoveOnly)>> boundTripleByValue = bin
d<MoveOnly, MoveOnly, MoveOnly>(tripleMoveOnlysByValues); |
| 465 EXPECT_EQ(6, (*boundTripleByValue)(MoveOnly(1), MoveOnly(2), MoveOnly(3))); |
| 466 } |
| 467 |
| 468 TEST(FunctionalTest, CountCopiesOfUnboundArguments) |
| 469 { |
| 470 CountCopy lvalue; |
| 471 OwnPtr<Function<int(const CountCopy&)>> bound1 = bind<const CountCopy&>(take
CountCopyAsConstReference); |
| 472 EXPECT_EQ(0, (*bound1)(lvalue)); // No copies! |
| 473 EXPECT_EQ(0, (*bound1)(CountCopy())); |
| 474 |
| 475 OwnPtr<Function<int(CountCopy)>> bound2 = bind<CountCopy>(takeCountCopyAsVal
ue); |
| 476 EXPECT_EQ(2, (*bound2)(lvalue)); // At PartBoundFunctionImpl::operator() and
at the destination function. |
| 477 EXPECT_LE((*bound2)(CountCopy()), 2); // Compiler is allowed to optimize one
copy away if the argument is rvalue. |
| 478 } |
| 479 |
| 425 } // anonymous namespace | 480 } // anonymous namespace |
| 426 | 481 |
| 427 } // namespace WTF | 482 } // namespace WTF |
| OLD | NEW |