diff --git a/include/rcp.h b/include/rcp.h index 96af0d7..feb4db6 100644 --- a/include/rcp.h +++ b/include/rcp.h @@ -70,6 +70,25 @@ public: return *this; } + rcp(rcp && other) noexcept : ptr(other.ptr) + { + other.ptr = nullptr; + } + + rcp & operator=(rcp && other) noexcept + { + if (ptr != other.ptr) + { + if (ptr) + { + ptr->rcp_dec(); + } + ptr = other.ptr; + other.ptr = nullptr; + } + return *this; + } + ~rcp() { if (ptr) diff --git a/test/tests.cpp b/test/tests.cpp index c24e664..ac8a3de 100644 --- a/test/tests.cpp +++ b/test/tests.cpp @@ -132,6 +132,55 @@ void test_copy_assignment_decrements_previous_reference() assert(myb->x == 14); } +void test_move_constructor() +{ + int constructed_before = mybase_construct; + int destructed_before = mybase_destruct; + { + MyB a = MyB::create(1, 2); + MyB b = std::move(a); + assert(!a); + assert(b); + assert(b->x == 1); + assert(mybase_destruct == destructed_before); + } + assert(mybase_construct == constructed_before + 1); + assert(mybase_destruct == destructed_before + 1); +} + +void test_move_assignment() +{ + int constructed_before = mybase_construct; + int destructed_before = mybase_destruct; + { + MyB a = MyB::create(1, 2); + MyB b; + b = std::move(a); + assert(!a); + assert(b); + assert(b->x == 1); + assert(mybase_destruct == destructed_before); + } + assert(mybase_construct == constructed_before + 1); + assert(mybase_destruct == destructed_before + 1); +} + +void test_move_assignment_releases_existing() +{ + int constructed_before = mybase_construct; + int destructed_before = mybase_destruct; + { + MyB a = MyB::create(1, 2); + MyB b = MyB::create(3, 4); + b = std::move(a); + assert(!a); + assert(b->x == 1); + assert(mybase_destruct == destructed_before + 1); + } + assert(mybase_construct == constructed_before + 2); + assert(mybase_destruct == destructed_before + 2); +} + int main(int argc, char * argv[]) { test_class_hierarchy(); @@ -140,5 +189,8 @@ int main(int argc, char * argv[]) test_create(); test_multi_construct_from_raw_pointers(); test_copy_assignment_decrements_previous_reference(); + test_move_constructor(); + test_move_assignment(); + test_move_assignment_releases_existing(); return 0; }