Skip to content

Commit 831bae7

Browse files
committed
Added static_pointer_cast
1 parent 26b65d7 commit 831bae7

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

include/oup/observable_unique_ptr.hpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,48 @@ class enable_observer_from_this : public virtual details::enable_observer_from_t
14091409
}
14101410
};
14111411

1412+
/// Perform a `static_cast` for an `observable_unique_ptr`.
1413+
/** \param ptr The pointer to cast
1414+
* \note Ownership will be transfered to the returned pointer.
1415+
If the input pointer is null, the output pointer will also be null.
1416+
*/
1417+
template<typename U, typename T>
1418+
observable_unique_ptr<U> static_pointer_cast(observable_unique_ptr<T>&& ptr) {
1419+
return observable_unique_ptr<U>(std::move(ptr), static_cast<U*>(ptr.get()));
1420+
}
1421+
1422+
/// Perform a `static_cast` for an `observable_unique_ptr`.
1423+
/** \param ptr The pointer to cast
1424+
* \note Ownership will be transfered to the returned pointer.
1425+
If the input pointer is null, the output pointer will also be null.
1426+
*/
1427+
template<typename U, typename T>
1428+
observable_sealed_ptr<U> static_pointer_cast(observable_sealed_ptr<T>&& ptr) {
1429+
return observable_sealed_ptr<U>(std::move(ptr), static_cast<U*>(ptr.get()));
1430+
}
1431+
1432+
/// Perform a `static_cast` for an `observer_ptr`.
1433+
/** \param ptr The pointer to cast
1434+
* \note A new observer is returned, the input observer is not modified.
1435+
If the input pointer is null, the output pointer will also be null.
1436+
*/
1437+
template<typename U, typename T>
1438+
observer_ptr<U> static_pointer_cast(const observer_ptr<T>& ptr) {
1439+
// NB: can use raw_get() as static cast of an expired pointer is fine
1440+
return observer_ptr<U>(ptr, static_cast<U*>(ptr.raw_get()));
1441+
}
1442+
1443+
/// Perform a `static_cast` for an `observer_ptr`.
1444+
/** \param ptr The pointer to cast
1445+
* \note A new observer is returned, the input observer is set to null.
1446+
If the input pointer is null, the output pointer will also be null.
1447+
*/
1448+
template<typename U, typename T>
1449+
observer_ptr<U> static_pointer_cast(observer_ptr<T>&& ptr) {
1450+
// NB: can use raw_get() as static cast of an expired pointer is fine
1451+
return observer_ptr<U>(std::move(ptr), static_cast<U*>(ptr.raw_get()));
1452+
}
1453+
14121454
}
14131455

14141456
#endif

tests/runtime_tests.cpp

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3481,3 +3481,147 @@ TEST_CASE("observer from this multiple inheritance", "[observer_from_this]") {
34813481
REQUIRE(mem_track.leaks() == 0u);
34823482
REQUIRE(mem_track.double_del() == 0u);
34833483
}
3484+
3485+
TEST_CASE("static pointer cast unique from valid", "[pointer_cast]") {
3486+
memory_tracker mem_track;
3487+
3488+
{
3489+
test_object_derived* raw_ptr = new test_object_derived;
3490+
test_ptr ptr_orig{raw_ptr};
3491+
test_ptr_derived ptr = oup::static_pointer_cast<test_object_derived>(std::move(ptr_orig));
3492+
3493+
REQUIRE(instances == 1);
3494+
REQUIRE(ptr_orig == nullptr);
3495+
REQUIRE(ptr.get() == raw_ptr);
3496+
}
3497+
3498+
REQUIRE(instances == 0);
3499+
REQUIRE(mem_track.leaks() == 0u);
3500+
REQUIRE(mem_track.double_del() == 0u);
3501+
}
3502+
3503+
TEST_CASE("static pointer cast unique from null", "[pointer_cast]") {
3504+
memory_tracker mem_track;
3505+
3506+
{
3507+
test_ptr ptr_orig;
3508+
test_ptr_derived ptr = oup::static_pointer_cast<test_object_derived>(std::move(ptr_orig));
3509+
3510+
REQUIRE(instances == 0);
3511+
REQUIRE(ptr_orig == nullptr);
3512+
REQUIRE(ptr == nullptr);
3513+
}
3514+
3515+
REQUIRE(instances == 0);
3516+
REQUIRE(mem_track.leaks() == 0u);
3517+
REQUIRE(mem_track.double_del() == 0u);
3518+
}
3519+
3520+
TEST_CASE("static pointer cast sealed from valid", "[pointer_cast]") {
3521+
memory_tracker mem_track;
3522+
3523+
{
3524+
test_sptr_derived ptr_init = oup::make_observable_sealed<test_object_derived>();
3525+
test_object_derived* raw_ptr = ptr_init.get();
3526+
test_sptr ptr_orig{std::move(ptr_init)};
3527+
test_sptr_derived ptr = oup::static_pointer_cast<test_object_derived>(std::move(ptr_orig));
3528+
3529+
REQUIRE(instances == 1);
3530+
REQUIRE(ptr_orig == nullptr);
3531+
REQUIRE(ptr.get() == raw_ptr);
3532+
}
3533+
3534+
REQUIRE(instances == 0);
3535+
REQUIRE(mem_track.leaks() == 0u);
3536+
REQUIRE(mem_track.double_del() == 0u);
3537+
}
3538+
3539+
TEST_CASE("static pointer cast sealed from null", "[pointer_cast]") {
3540+
memory_tracker mem_track;
3541+
3542+
{
3543+
test_sptr ptr_orig;
3544+
test_sptr_derived ptr = oup::static_pointer_cast<test_object_derived>(std::move(ptr_orig));
3545+
3546+
REQUIRE(instances == 0);
3547+
REQUIRE(ptr_orig == nullptr);
3548+
REQUIRE(ptr == nullptr);
3549+
}
3550+
3551+
REQUIRE(instances == 0);
3552+
REQUIRE(mem_track.leaks() == 0u);
3553+
REQUIRE(mem_track.double_del() == 0u);
3554+
}
3555+
3556+
TEST_CASE("static pointer cast observer copy from valid", "[pointer_cast]") {
3557+
memory_tracker mem_track;
3558+
3559+
{
3560+
test_sptr_derived ptr_owner = oup::make_observable_sealed<test_object_derived>();
3561+
test_object_derived* raw_ptr = ptr_owner.get();
3562+
test_optr ptr_orig{ptr_owner};
3563+
test_optr_derived ptr = oup::static_pointer_cast<test_object_derived>(ptr_orig);
3564+
3565+
REQUIRE(instances == 1);
3566+
REQUIRE(ptr_orig.get() == raw_ptr);
3567+
REQUIRE(ptr.get() == raw_ptr);
3568+
}
3569+
3570+
REQUIRE(instances == 0);
3571+
REQUIRE(mem_track.leaks() == 0u);
3572+
REQUIRE(mem_track.double_del() == 0u);
3573+
}
3574+
3575+
TEST_CASE("static pointer cast observer copy from null", "[pointer_cast]") {
3576+
memory_tracker mem_track;
3577+
3578+
{
3579+
test_optr ptr_orig;
3580+
test_optr_derived ptr = oup::static_pointer_cast<test_object_derived>(ptr_orig);
3581+
3582+
REQUIRE(instances == 0);
3583+
REQUIRE(ptr_orig == nullptr);
3584+
REQUIRE(ptr == nullptr);
3585+
}
3586+
3587+
REQUIRE(instances == 0);
3588+
REQUIRE(mem_track.leaks() == 0u);
3589+
REQUIRE(mem_track.double_del() == 0u);
3590+
}
3591+
3592+
3593+
TEST_CASE("static pointer cast observer move from valid", "[pointer_cast]") {
3594+
memory_tracker mem_track;
3595+
3596+
{
3597+
test_sptr_derived ptr_owner = oup::make_observable_sealed<test_object_derived>();
3598+
test_object_derived* raw_ptr = ptr_owner.get();
3599+
test_optr ptr_orig{ptr_owner};
3600+
test_optr_derived ptr = oup::static_pointer_cast<test_object_derived>(std::move(ptr_orig));
3601+
3602+
REQUIRE(instances == 1);
3603+
REQUIRE(ptr_orig == nullptr);
3604+
REQUIRE(ptr.get() == raw_ptr);
3605+
}
3606+
3607+
REQUIRE(instances == 0);
3608+
REQUIRE(mem_track.leaks() == 0u);
3609+
REQUIRE(mem_track.double_del() == 0u);
3610+
}
3611+
3612+
TEST_CASE("static pointer cast observer move from null", "[pointer_cast]") {
3613+
memory_tracker mem_track;
3614+
3615+
{
3616+
test_optr ptr_orig;
3617+
test_optr_derived ptr = oup::static_pointer_cast<test_object_derived>(std::move(ptr_orig));
3618+
3619+
REQUIRE(instances == 0);
3620+
REQUIRE(ptr_orig == nullptr);
3621+
REQUIRE(ptr == nullptr);
3622+
}
3623+
3624+
REQUIRE(instances == 0);
3625+
REQUIRE(mem_track.leaks() == 0u);
3626+
REQUIRE(mem_track.double_del() == 0u);
3627+
}

0 commit comments

Comments
 (0)