Skip to content

Commit 91ef2e1

Browse files
committed
Support enable_observer_from_this with derived classes
1 parent cd42aba commit 91ef2e1

File tree

3 files changed

+37
-2
lines changed

3 files changed

+37
-2
lines changed

include/oup/observable_unique_ptr.hpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ template<typename T>
1515
class enable_observer_from_this;
1616

1717
namespace details {
18+
1819
struct control_block {
1920
enum flag_elements {
2021
flag_none = 0,
@@ -37,6 +38,7 @@ template<typename T, typename Deleter>
3738
struct ptr_and_deleter : Deleter {
3839
T* data = nullptr;
3940
};
41+
4042
}
4143

4244
/// Simple default deleter
@@ -78,6 +80,9 @@ struct placement_delete
7880
};
7981

8082
namespace details {
83+
84+
struct enable_observer_from_this_base {};
85+
8186
template<typename T, typename Deleter = oup::default_delete<T>>
8287
class observable_unique_ptr_base {
8388
protected:
@@ -111,7 +116,7 @@ class observable_unique_ptr_base {
111116

112117
/// Fill in the observer pointer for objects inheriting from enable_observer_from_this.
113118
void set_this_observer_() noexcept {
114-
if constexpr (std::is_base_of_v<enable_observer_from_this<T>, T>) {
119+
if constexpr (std::is_base_of_v<details::enable_observer_from_this_base, T>) {
115120
if (ptr_deleter.data) {
116121
ptr_deleter.data->this_observer.set_data_(block, ptr_deleter.data);
117122
++block->refcount;
@@ -362,6 +367,7 @@ class observable_unique_ptr_base {
362367
return ptr_deleter.data != nullptr;
363368
}
364369
};
370+
365371
}
366372

367373
/// Unique-ownership smart pointer, can be observed by observer_ptr, ownership can be released.
@@ -1180,7 +1186,7 @@ bool operator!= (const observer_ptr<T>& first, const observer_ptr<U>& second) no
11801186
* type of smart pointer, then observer_from_this() will return nullptr.
11811187
*/
11821188
template<typename T>
1183-
class enable_observer_from_this {
1189+
class enable_observer_from_this : public details::enable_observer_from_this_base {
11841190
mutable observer_ptr<T> this_observer;
11851191

11861192
// Friendship is required for assignment of the observer.

tests/runtime_tests.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2961,6 +2961,28 @@ TEST_CASE("observer from this sealed", "[observer_from_this]") {
29612961
REQUIRE(mem_track.double_del() == 0u);
29622962
}
29632963

2964+
TEST_CASE("observer from this derived", "[observer_from_this]") {
2965+
memory_tracker mem_track;
2966+
2967+
{
2968+
test_ptr_from_this_derived ptr{new test_object_observer_from_this_derived};
2969+
const test_ptr_from_this_derived& cptr = ptr;
2970+
2971+
test_optr_from_this optr_from_this = ptr->observer_from_this();
2972+
test_optr_from_this_const optr_from_this_const = cptr->observer_from_this();
2973+
2974+
REQUIRE(instances == 1);
2975+
REQUIRE(optr_from_this.expired() == false);
2976+
REQUIRE(optr_from_this_const.expired() == false);
2977+
REQUIRE(optr_from_this.get() == ptr.get());
2978+
REQUIRE(optr_from_this_const.get() == ptr.get());
2979+
}
2980+
2981+
REQUIRE(instances == 0);
2982+
REQUIRE(mem_track.leaks() == 0u);
2983+
REQUIRE(mem_track.double_del() == 0u);
2984+
}
2985+
29642986
TEST_CASE("observer from this after move", "[observer_from_this]") {
29652987
memory_tracker mem_track;
29662988

tests/tests_common.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ struct test_object_observer_from_this :
4242
public test_object,
4343
public oup::enable_observer_from_this<test_object_observer_from_this> {};
4444

45+
struct test_object_observer_from_this_derived :
46+
public test_object_observer_from_this {};
47+
4548
struct test_deleter {
4649
int state_ = 0;
4750

@@ -79,8 +82,12 @@ using test_sptr_thrower = oup::observable_sealed_ptr<test_object_thrower>;
7982
using test_ptr_thrower_with_deleter = oup::observable_unique_ptr<test_object_thrower,test_deleter>;
8083
using test_ptr_from_this = oup::observable_unique_ptr<test_object_observer_from_this>;
8184
using test_sptr_from_this = oup::observable_sealed_ptr<test_object_observer_from_this>;
85+
using test_ptr_from_this_derived = oup::observable_unique_ptr<test_object_observer_from_this_derived>;
86+
using test_sptr_from_this_derived = oup::observable_sealed_ptr<test_object_observer_from_this_derived>;
8287

8388
using test_optr = oup::observer_ptr<test_object>;
8489
using test_optr_derived = oup::observer_ptr<test_object_derived>;
8590
using test_optr_from_this = oup::observer_ptr<test_object_observer_from_this>;
8691
using test_optr_from_this_const = oup::observer_ptr<const test_object_observer_from_this>;
92+
using test_optr_from_this_derived = oup::observer_ptr<test_object_observer_from_this_derived>;
93+
using test_optr_from_this_derived_const = oup::observer_ptr<const test_object_observer_from_this_derived>;

0 commit comments

Comments
 (0)