Skip to content

Commit e5318fa

Browse files
committed
Simple .shared_from_this() experiments.
1 parent 56bfadd commit e5318fa

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/* clang++ -std=c++11 shared_from_this_custom_deleters.cpp && a.out
2+
3+
Simple experiment, to show that `.shared_from_this()` ~only retrieves
4+
the first `shared_ptr` created for a given pointee. (See obj1_reset() for
5+
a more complete story.)
6+
*/
7+
8+
#include <iostream>
9+
#include <memory>
10+
11+
template <typename T>
12+
struct labeled_delete {
13+
std::string label;
14+
explicit labeled_delete(const std::string& label) : label{label} {}
15+
void operator()(T* raw_ptr) {
16+
std::cout << "labeled_delete::operator() " << label << std::endl;
17+
if (label != "SkipDelete") {
18+
delete raw_ptr;
19+
}
20+
}
21+
};
22+
23+
struct Atype : std::enable_shared_from_this<Atype> {};
24+
25+
#define SHOW_USE_COUNTS \
26+
std::cout << "obj1, obj2 use_counts: " << obj1.use_count() << ", " \
27+
<< obj2.use_count() << std::endl;
28+
29+
void obj1_owns() {
30+
std::cout << "\nobj1_owns()" << std::endl;
31+
std::shared_ptr<Atype> obj1(new Atype, labeled_delete<Atype>("1st"));
32+
std::shared_ptr<Atype> obj2(obj1.get(), labeled_delete<Atype>("SkipDelete"));
33+
SHOW_USE_COUNTS
34+
auto sft1 = obj1->shared_from_this();
35+
SHOW_USE_COUNTS
36+
auto sft2 = obj2->shared_from_this();
37+
SHOW_USE_COUNTS
38+
}
39+
/* Expected output:
40+
obj1_owns()
41+
obj1, obj2 use_counts: 1, 1
42+
obj1, obj2 use_counts: 2, 1
43+
obj1, obj2 use_counts: 3, 1
44+
labeled_delete::operator() SkipDelete
45+
labeled_delete::operator() 1st
46+
*/
47+
48+
void obj2_owns() {
49+
std::cout << "\nobj2_owns()" << std::endl;
50+
std::shared_ptr<Atype> obj1(new Atype, labeled_delete<Atype>("SkipDelete"));
51+
std::shared_ptr<Atype> obj2(obj1.get(), labeled_delete<Atype>("2nd"));
52+
SHOW_USE_COUNTS
53+
auto sft1 = obj1->shared_from_this();
54+
SHOW_USE_COUNTS
55+
auto sft2 = obj2->shared_from_this();
56+
SHOW_USE_COUNTS
57+
}
58+
/* Expected output:
59+
obj2_owns()
60+
obj1, obj2 use_counts: 1, 1
61+
obj1, obj2 use_counts: 2, 1
62+
obj1, obj2 use_counts: 3, 1
63+
labeled_delete::operator() 2nd
64+
labeled_delete::operator() SkipDelete
65+
*/
66+
67+
void obj1_reset() {
68+
std::cout << "\nobj1_reset()" << std::endl;
69+
std::shared_ptr<Atype> obj1(new Atype, labeled_delete<Atype>("SkipDelete"));
70+
std::shared_ptr<Atype> obj2(obj1.get(), labeled_delete<Atype>("ThisDeletes"));
71+
obj1->shared_from_this();
72+
obj2->shared_from_this();
73+
obj1.reset();
74+
bool got_bad_weak_ptr = false;
75+
try {
76+
obj2->shared_from_this();
77+
} catch (const std::bad_weak_ptr&) {
78+
got_bad_weak_ptr = true;
79+
}
80+
std::cout << "got_bad_weak_ptr: " << got_bad_weak_ptr << std::endl;
81+
std::shared_ptr<Atype> obj3(obj2.get(), labeled_delete<Atype>("SkipDelete"));
82+
// Working again based on the shared_ptr that was created after obj1 was
83+
// reset:
84+
obj2->shared_from_this();
85+
}
86+
/* Expected output:
87+
obj1_reset()
88+
labeled_delete::operator() SkipDelete
89+
got_bad_weak_ptr: 1
90+
labeled_delete::operator() SkipDelete
91+
labeled_delete::operator() ThisDeletes
92+
*/
93+
94+
int main() {
95+
obj1_owns();
96+
obj2_owns();
97+
obj1_reset();
98+
return 0;
99+
}

0 commit comments

Comments
 (0)