throwing_ptr
Smart pointers that throw on dereference if null
shared_ptr_construction.cpp
Go to the documentation of this file.
1 // Copyright Claudio Bantaloukas 2017-2018.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 
6 #include <catch.hpp>
7 #include <throwing/shared_ptr.hpp>
8 
9 namespace {
10 class A {
11  int dummy_a;
12 
13 public:
14  int dummy() { return dummy_a; }
15 };
16 
17 class B : public A {
18  int dummy_b;
19 
20 public:
21  int dummy() { return dummy_b; }
22 };
23 
24 struct A_D {
25  void operator()(A *p) const { delete p; }
26 };
27 
28 struct Contained {
29  // some data that we want to point to
30  int dummy_;
31  int dummy() { return dummy_; }
32 };
33 
34 struct Container {
35  Contained things;
36 };
37 } // namespace
38 
39 TEST_CASE("shared_ptr constructor from pointer", "[shared_ptr][constructor]") {
40  A *ptr1 = new A;
41  throwing::shared_ptr<A> t_ptr1(ptr1);
42  REQUIRE(t_ptr1.get() == ptr1);
43 }
44 
45 TEST_CASE("shared_ptr constructor from pointer and deleter",
46  "[shared_ptr][constructor]") {
47  A *ptr1 = new A;
48  throwing::shared_ptr<A> t_ptr1(ptr1, A_D());
49  REQUIRE(t_ptr1.get() == ptr1);
50  REQUIRE(throwing::get_deleter<A_D>(t_ptr1) != nullptr);
51 }
52 
53 TEST_CASE("shared_ptr constructor from pointer and lambda deleter",
54  "Construction") {
55  A *ptr1 = new A;
56  bool lamda_called = false;
57  {
58  throwing::shared_ptr<A> t_ptr1(ptr1, [&lamda_called](A *p) {
59  delete p;
60  lamda_called = true;
61  });
62  REQUIRE(t_ptr1.get() == ptr1);
63  REQUIRE_FALSE(lamda_called);
64  }
65  REQUIRE(lamda_called);
66 }
67 
68 TEST_CASE("shared_ptr constructor from pointer to derived class",
69  "[shared_ptr][constructor]") {
70  B *ptr1 = new B;
71  throwing::shared_ptr<A> t_ptr1(ptr1);
72  REQUIRE(t_ptr1.get() == ptr1);
73 }
74 
75 TEST_CASE("shared_ptr constructor from pointer to base type",
76  "[shared_ptr][constructor]") {
77  int *ptr1 = new int;
78  throwing::shared_ptr<int> t_ptr1(ptr1);
79  REQUIRE(t_ptr1.get() == ptr1);
80 }
81 
82 TEST_CASE("shared_ptr constructor from nullptr and deleter",
83  "[shared_ptr][constructor]") {
84  bool lamda_called = false;
85  {
86  throwing::shared_ptr<A> t_ptr1(nullptr, [&lamda_called](A *p) {
87  delete p;
88  lamda_called = true;
89  });
90  REQUIRE(t_ptr1.get() == nullptr);
91  REQUIRE_FALSE(lamda_called);
92  }
93  REQUIRE(lamda_called);
94 }
95 
96 TEST_CASE("shared_ptr constructor from nullptr, lambda deleter and allocator",
97  "[shared_ptr][constructor]") {
98  A *ptr1 = new A;
99  std::allocator<void *> allocator;
100  bool lamda_called = false;
101  {
102  throwing::shared_ptr<A> t_ptr1(ptr1,
103  [&lamda_called](A *p) {
104  delete p;
105  lamda_called = true;
106  },
107  allocator);
108  REQUIRE(t_ptr1.get() == ptr1);
109  REQUIRE_FALSE(lamda_called);
110  }
111  REQUIRE(lamda_called);
112 }
113 
114 TEST_CASE("shared_ptr aliasing constructor", "[shared_ptr][constructor]") {
115  Container *ptr1 = new Container;
116  bool lamda_called = false;
117  {
118  throwing::shared_ptr<Container> t_ptr1(ptr1,
119  [&lamda_called](Container *p) {
120  delete p;
121  lamda_called = true;
122  });
123  REQUIRE(t_ptr1.get() == ptr1);
124  REQUIRE_FALSE(lamda_called);
125  auto via_aliasing =
126  throwing::shared_ptr<Contained>(t_ptr1, &ptr1->things);
127  REQUIRE_FALSE(lamda_called);
128  t_ptr1.reset();
129  REQUIRE_FALSE(lamda_called);
130  via_aliasing.reset();
131  REQUIRE(lamda_called);
132  }
133 }
134 
135 TEST_CASE("shared_ptr copy constructor", "[shared_ptr][constructor]") {
136  A *ptr1 = new A;
137  auto t_ptr1 = throwing::shared_ptr<A>(ptr1);
138  throwing::shared_ptr<A> t_ptr2(t_ptr1);
139  REQUIRE(t_ptr2.get() == t_ptr1.get());
140  t_ptr1.reset();
141  REQUIRE(t_ptr2.get() == ptr1);
142 }
143 
144 TEST_CASE("shared_ptr copy constructor from derived", "Construction") {
145  B *ptr1 = new B;
146  auto t_ptr1 = throwing::shared_ptr<B>(ptr1);
147  throwing::shared_ptr<A> t_ptr2 = t_ptr1;
148  REQUIRE(t_ptr2.get() == t_ptr1.get());
149  t_ptr1.reset();
150  REQUIRE(t_ptr2.get() == ptr1);
151 }
152 
153 TEST_CASE("shared_ptr move constructor", "[shared_ptr][constructor]") {
154  A *ptr1 = new A;
155  auto t_ptr1 = throwing::shared_ptr<A>(ptr1);
156  throwing::shared_ptr<A> t_ptr2(std::move(t_ptr1));
157  REQUIRE(t_ptr1.get() == nullptr);
158  REQUIRE(t_ptr2.get() == ptr1);
159 }
160 
161 TEST_CASE("shared_ptr move constructor from derived",
162  "[shared_ptr][constructor]") {
163  B *ptr1 = new B;
164  auto t_ptr1 = throwing::shared_ptr<B>(ptr1);
165  throwing::shared_ptr<A> t_ptr2(std::move(t_ptr1));
166  REQUIRE(t_ptr1.get() == nullptr);
167  REQUIRE(t_ptr2.get() == ptr1);
168 }
169 
170 TEST_CASE("shared_ptr constructor from std::shared_ptr",
171  "[shared_ptr][constructor]") {
172  A *ptr1 = new A;
173  auto t_ptr1 = std::shared_ptr<A>(ptr1);
174  throwing::shared_ptr<A> t_ptr2(t_ptr1);
175  REQUIRE(t_ptr2.get() == t_ptr1.get());
176  t_ptr1.reset();
177  REQUIRE(t_ptr2.get() == ptr1);
178 }
179 
180 TEST_CASE("shared_ptr constructor from std::shared_ptr to derived",
181  "[shared_ptr][constructor]") {
182  B *ptr1 = new B;
183  auto t_ptr1 = std::shared_ptr<B>(ptr1);
184  throwing::shared_ptr<A> t_ptr2(t_ptr1);
185  REQUIRE(t_ptr2.get() == t_ptr1.get());
186  t_ptr1.reset();
187  REQUIRE(t_ptr2.get() == ptr1);
188 }
189 
190 TEST_CASE("shared_ptr move constructor from std::shared_ptr",
191  "[shared_ptr][constructor]") {
192  A *ptr1 = new A;
193  auto t_ptr1 = std::shared_ptr<A>(ptr1);
194  throwing::shared_ptr<A> t_ptr2(std::move(t_ptr1));
195  REQUIRE(t_ptr1.get() == nullptr);
196  REQUIRE(t_ptr2.get() == ptr1);
197 }
198 
199 TEST_CASE("shared_ptr move constructor from std::shared_ptr to derived",
200  "[shared_ptr][constructor]") {
201  B *ptr1 = new B;
202  auto t_ptr1 = std::shared_ptr<B>(ptr1);
203  throwing::shared_ptr<A> t_ptr2(std::move(t_ptr1));
204  REQUIRE(t_ptr1.get() == nullptr);
205  REQUIRE(t_ptr2.get() == ptr1);
206 }
207 
208 TEST_CASE("shared_ptr constructor from derived std::weak_ptr",
209  "[shared_ptr][constructor]") {
210  B *ptr1 = new B;
211  auto t_ptr1 = std::shared_ptr<B>(ptr1);
212  std::weak_ptr<B> weak = t_ptr1;
213  throwing::shared_ptr<A> t_ptr2(weak);
214  REQUIRE(t_ptr2.get() == t_ptr1.get());
215  t_ptr1.reset();
216  REQUIRE(t_ptr2.get() == ptr1);
217 }
218 
219 TEST_CASE("shared_ptr move constructor from std::unique_ptr",
220  "[shared_ptr][constructor]") {
221  B *ptr1 = new B;
222  auto u_ptr1 = std::unique_ptr<B>(ptr1);
223  throwing::shared_ptr<A> t_ptr2(std::move(u_ptr1));
224  REQUIRE(u_ptr1.get() == nullptr);
225  REQUIRE(t_ptr2.get() == ptr1);
226 }
TEST_CASE("unique_ptr to array reset to convertible", "[unique_ptr][array][reset][conv.qual]")