#include #include #include static int mybase_construct; static int mybase_destruct; static int myderived_construct; static int myderived_destruct; class MyBase { rcp_managed_root(MyBase); protected: MyBase(int x, int y) { this->x = x; this->y = y; mybase_construct++; } virtual ~MyBase() { mybase_destruct++; } public: int x; int y; }; typedef rcp MyB; class MyDerived : public MyBase { rcp_managed(MyDerived); protected: MyDerived(double v) : MyBase(1, 2) { this->v = v; myderived_construct++; } virtual ~MyDerived() { myderived_destruct++; } public: double v; }; void test_class_hierarchy() { { rcp mybase = MyBase::create(4, 5); rcp myderived = MyDerived::create(42.5); } assert(mybase_construct == 2); assert(mybase_destruct == 2); assert(myderived_construct == 1); assert(myderived_destruct == 1); } void test_dereference() { rcp mybase = MyBase::create(2, 3); assert(mybase->x == 2); assert(mybase->y == 3); assert((*mybase).x == 2); assert((*mybase).y == 3); rcp mybase2 = mybase; assert(mybase == mybase2); assert(!(mybase != mybase2)); } void test_booleans() { rcp mybase = MyBase::create(2, 3); assert(mybase); assert(mybase != nullptr); rcp myderived; assert(!myderived); assert(myderived == nullptr); } void test_create() { MyB myb = MyB::create(8, 9); assert(myb->x == 8); } struct MyObj { rcp_managed_root(MyObj); public: int v = {42}; template void add_to(R & receiver) { receiver.add(this); } }; struct Receiver { std::vector> objects; void add(MyObj * o) { objects.push_back(rcp(o)); } }; void test_multi_construct_from_raw_pointers() { Receiver r; auto myo = MyObj::create(); for (size_t i = 0u; i < 5u; i++) { myo->add_to(r); } for (size_t i = 0u; i < 5u; i++) { assert(r.objects[i]->v == 42); } } void test_copy_assignment_decrements_previous_reference() { MyB myb = MyB::create(12, 13); MyB myb2 = MyB::create(14, 15); myb = myb2; 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); } void test_cross_type_comparison() { rcp derived = MyDerived::create(1.5); rcp base = derived; assert(base == derived); assert(!(base != derived)); rcp other = MyBase::create(1, 2); assert(base != other); assert(!(base == other)); } void test_reset() { int destructed_before = mybase_destruct; MyB p = MyB::create(1, 2); p.reset(); assert(!p); assert(mybase_destruct == destructed_before + 1); } void test_upcast() { rcp derived = MyDerived::create(1.5); rcp base = derived; assert(base); assert(base->x == 1); } void test_move_upcast() { int constructed_before = mybase_construct; int destructed_before = mybase_destruct; { rcp derived = MyDerived::create(1.5); rcp base = std::move(derived); assert(!derived); assert(base); assert(base->x == 1); assert(mybase_destruct == destructed_before); } assert(mybase_construct == constructed_before + 1); assert(mybase_destruct == destructed_before + 1); } void test_dynamic_cast_success() { rcp derived = MyDerived::create(1.5); rcp base = derived; rcp back = rcp_dynamic_cast(base); assert(back); assert(back->v == 1.5); } void test_dynamic_cast_move_success() { int constructed_before = mybase_construct; int destructed_before = mybase_destruct; { rcp base = MyDerived::create(1.5); rcp derived = rcp_dynamic_cast(std::move(base)); assert(!base); assert(derived); assert(derived->v == 1.5); assert(mybase_destruct == destructed_before); } assert(mybase_construct == constructed_before + 1); assert(mybase_destruct == destructed_before + 1); } void test_dynamic_cast_move_failure() { rcp base = MyBase::create(1, 2); rcp derived = rcp_dynamic_cast(std::move(base)); assert(!derived); assert(base); } void test_dynamic_cast_failure() { rcp base = MyBase::create(1, 2); rcp derived = rcp_dynamic_cast(base); assert(!derived); } int main(int argc, char * argv[]) { test_class_hierarchy(); test_dereference(); test_booleans(); test_create(); test_multi_construct_from_raw_pointers(); test_copy_assignment_decrements_previous_reference(); test_cross_type_comparison(); test_reset(); test_move_constructor(); test_move_assignment(); test_move_assignment_releases_existing(); test_upcast(); test_move_upcast(); test_dynamic_cast_success(); test_dynamic_cast_failure(); test_dynamic_cast_move_success(); test_dynamic_cast_move_failure(); return 0; }