Skip to content

Commit fe1cba8

Browse files
committed
Return reference from methods that cannot return a nullpointer
Previously some methods returned a pointer but would never return nullptr. This changes their return type to references instead.
1 parent 5607f39 commit fe1cba8

File tree

4 files changed

+48
-117
lines changed

4 files changed

+48
-117
lines changed

src/util/as_const.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ const T &as_const(T &value)
1616
return static_cast<const T &>(value);
1717
}
1818

19+
/// Return a pointer to the same object but ensures the type is pointer to const
20+
template <typename T>
21+
const T *as_const_ptr(T *t)
22+
{
23+
return t;
24+
}
25+
1926
/// Deleted to avoid calling as_const on an xvalue
2027
template <typename T>
2128
void as_const(T &&) = delete;

src/util/sharing_map.h

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Author: Daniel Poetzl
2727
#include <type_traits>
2828
#include <vector>
2929

30+
#include "as_const.h"
3031
#include "irep.h"
3132
#include "optional.h"
3233
#include "sharing_node.h"
@@ -518,7 +519,7 @@ class sharing_mapt
518519
protected:
519520
// helpers
520521

521-
leaft *get_leaf_node(const key_type &k);
522+
leaft &get_leaf_node(const key_type &k);
522523
const leaft *get_leaf_node(const key_type &k) const;
523524

524525
/// Move a leaf node further down the tree such as to resolve a collision with
@@ -1062,7 +1063,7 @@ ::get_delta_view(
10621063
while(!stack.empty());
10631064
}
10641065

1065-
SHARING_MAPT2(, leaft *)::get_leaf_node(const key_type &k)
1066+
SHARING_MAPT2(, leaft &)::get_leaf_node(const key_type &k)
10661067
{
10671068
SM_ASSERT(has_key(k));
10681069

@@ -1074,9 +1075,8 @@ SHARING_MAPT2(, leaft *)::get_leaf_node(const key_type &k)
10741075
{
10751076
std::size_t bit = key & mask;
10761077

1077-
ip = ip->add_child(bit);
1078-
SM_ASSERT(ip != nullptr);
1079-
SM_ASSERT(!ip->empty()); // since the key must exist in the map
1078+
ip = &ip->add_child(bit);
1079+
PRECONDITION(!ip->empty()); // since the key must exist in the map
10801080

10811081
if(ip->is_internal())
10821082
{
@@ -1085,17 +1085,14 @@ SHARING_MAPT2(, leaft *)::get_leaf_node(const key_type &k)
10851085
}
10861086
else if(ip->is_leaf())
10871087
{
1088-
return ip;
1088+
return *ip;
10891089
}
10901090
else
10911091
{
10921092
SM_ASSERT(ip->is_defined_container());
1093-
return ip->find_leaf(k);
1093+
return *ip->find_leaf(k);
10941094
}
10951095
}
1096-
1097-
UNREACHABLE;
1098-
return nullptr;
10991096
}
11001097

11011098
SHARING_MAPT2(const, leaft *)::get_leaf_node(const key_type &k) const
@@ -1152,15 +1149,15 @@ SHARING_MAPT(void)::erase(const key_type &k)
11521149
{
11531150
std::size_t bit = key & mask;
11541151

1155-
const to_mapt &m = as_const(ip)->get_to_map();
1152+
const to_mapt &m = as_const_ptr(ip)->get_to_map();
11561153

11571154
if(m.size() > 1 || del == nullptr)
11581155
{
11591156
del = ip;
11601157
del_bit=bit;
11611158
}
11621159

1163-
ip = ip->add_child(bit);
1160+
ip = &ip->add_child(bit);
11641161

11651162
PRECONDITION(!ip->empty());
11661163

@@ -1181,7 +1178,8 @@ SHARING_MAPT(void)::erase(const key_type &k)
11811178
else
11821179
{
11831180
SM_ASSERT(ip->is_defined_container());
1184-
const leaf_listt &ll = as_const(ip)->get_container();
1181+
const leaf_listt &ll = as_const_ptr(ip)->get_container();
1182+
PRECONDITION(!ll.empty());
11851183

11861184
// forward list has one element
11871185
if(std::next(ll.begin()) == ll.end())
@@ -1215,7 +1213,7 @@ ::migrate(
12151213
SM_ASSERT(starting_level < levels - 1);
12161214
SM_ASSERT(inner.is_defined_internal());
12171215

1218-
leaft &leaf = *inner.add_child(bit_last);
1216+
leaft &leaf = inner.add_child(bit_last);
12191217
SM_ASSERT(leaf.is_defined_leaf());
12201218

12211219
std::size_t key_existing = hash()(leaf.get_key());
@@ -1248,19 +1246,19 @@ ::migrate(
12481246
{
12491247
// Place found
12501248

1251-
innert *l1 = ip->add_child(bit_existing);
1252-
SM_ASSERT(l1->empty());
1253-
l1->swap(leaf_kept);
1249+
innert &l1 = ip->add_child(bit_existing);
1250+
SM_ASSERT(l1.empty());
1251+
l1.swap(leaf_kept);
12541252

1255-
innert *l2 = ip->add_child(bit);
1256-
SM_ASSERT(l2->empty());
1257-
l2->make_leaf(k, std::forward<valueU>(m));
1253+
innert &l2 = ip->add_child(bit);
1254+
SM_ASSERT(l2.empty());
1255+
l2.make_leaf(k, std::forward<valueU>(m));
12581256

12591257
return;
12601258
}
12611259

12621260
SM_ASSERT(bit == bit_existing);
1263-
ip = ip->add_child(bit);
1261+
ip = &ip->add_child(bit);
12641262

12651263
key >>= chunk;
12661264
key_existing >>= chunk;
@@ -1302,39 +1300,39 @@ ::insert(const key_type &k, valueU &&m)
13021300
SM_ASSERT(ip->is_internal());
13031301
SM_ASSERT(level == 0 || !ip->empty());
13041302

1305-
innert *child = ip->add_child(bit);
1303+
innert &child = ip->add_child(bit);
13061304

13071305
// Place is unoccupied
1308-
if(child->empty())
1306+
if(child.empty())
13091307
{
13101308
if(level < levels - 1)
13111309
{
13121310
// Create leaf
1313-
child->make_leaf(k, m);
1311+
child.make_leaf(k, m);
13141312
}
13151313
else
13161314
{
13171315
SM_ASSERT(level == levels - 1);
13181316

13191317
// Create container and insert leaf
1320-
child->place_leaf(k, std::forward<valueU>(m));
1318+
child.place_leaf(k, std::forward<valueU>(m));
13211319

1322-
SM_ASSERT(child->is_defined_container());
1320+
SM_ASSERT(child.is_defined_container());
13231321
}
13241322

13251323
num++;
13261324

13271325
return;
13281326
}
1329-
else if(child->is_internal())
1327+
else if(child.is_internal())
13301328
{
1331-
ip = child;
1329+
ip = &child;
13321330
key >>= chunk;
13331331
level++;
13341332

13351333
continue;
13361334
}
1337-
else if(child->is_leaf())
1335+
else if(child.is_leaf())
13381336
{
13391337
// migrate leaf downwards
13401338
migrate(level, key, bit, *ip, k, std::forward<valueU>(m));
@@ -1345,11 +1343,11 @@ ::insert(const key_type &k, valueU &&m)
13451343
}
13461344
else
13471345
{
1348-
SM_ASSERT(child->is_defined_container());
1346+
SM_ASSERT(child.is_defined_container());
13491347
SM_ASSERT(level == levels - 1);
13501348

13511349
// Add to the container
1352-
child->place_leaf(k, std::forward<valueU>(m));
1350+
child.place_leaf(k, std::forward<valueU>(m));
13531351

13541352
num++;
13551353

@@ -1361,28 +1359,26 @@ ::insert(const key_type &k, valueU &&m)
13611359
SHARING_MAPT4(valueU, void)
13621360
::replace(const key_type &k, valueU &&m)
13631361
{
1364-
leaft *lp = get_leaf_node(k);
1365-
PRECONDITION(lp != nullptr); // key must exist in map
1362+
leaft &lp = get_leaf_node(k);
13661363

13671364
INVARIANT(
1368-
!value_equalt()(as_const(lp)->get_value(), m),
1365+
!value_equalt()(as_const(lp).get_value(), m),
13691366
"values should not be replaced with equal values to maximize sharing");
13701367

1371-
lp->set_value(std::forward<valueU>(m));
1368+
lp.set_value(std::forward<valueU>(m));
13721369
}
13731370

13741371
SHARING_MAPT(void)
13751372
::update(const key_type &k, std::function<void(mapped_type &)> mutator)
13761373
{
1377-
leaft *lp = get_leaf_node(k);
1378-
PRECONDITION(lp != nullptr); // key must exist in map
1374+
leaft &lp = get_leaf_node(k);
13791375

1380-
value_comparatort comparator(as_const(lp)->get_value());
1376+
value_comparatort comparator(as_const(lp).get_value());
13811377

1382-
lp->mutate_value(mutator);
1378+
lp.mutate_value(mutator);
13831379

13841380
INVARIANT(
1385-
!comparator(as_const(lp)->get_value()),
1381+
!comparator(as_const(lp).get_value()),
13861382
"sharing_mapt::update should make some change. Consider using read-only "
13871383
"method to check if an update is needed beforehand");
13881384
}

src/util/sharing_node.h

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Author: Daniel Poetzl
3333
#include <map>
3434
#endif
3535

36+
#include "as_const.h"
3637
#include "invariant.h"
3738
#include "make_unique.h"
3839
#include "small_shared_n_way_ptr.h"
@@ -61,12 +62,6 @@ Author: Daniel Poetzl
6162
d_internalt<SN_TYPE_ARGS>, d_containert<SN_TYPE_ARGS>, d_leaft<SN_TYPE_ARGS>
6263
// clang-format on
6364

64-
template <class T>
65-
const T *as_const(T *t)
66-
{
67-
return t;
68-
}
69-
7065
typedef small_shared_n_way_pointee_baset<3, unsigned> d_baset;
7166

7267
SN_TYPE_PAR_DECL class sharing_nodet;
@@ -289,19 +284,17 @@ SN_TYPE_PAR_DEF class sharing_nodet
289284

290285
// add leaf, key must not exist yet
291286
template <class valueU>
292-
leaft *place_leaf(const keyT &k, valueU &&v)
287+
void place_leaf(const keyT &k, valueU &&v)
293288
{
294289
SN_ASSERT(is_container()); // empty() is allowed
295290

296291
// we need to check empty() first as the const version of find_leaf() must
297292
// not be called on an empty node
298-
PRECONDITION(empty() || as_const(this)->find_leaf(k) == nullptr);
293+
PRECONDITION(empty() || as_const(*this).find_leaf(k) == nullptr);
299294

300295
leaf_listt &c = get_container();
301296
c.emplace_front(k, std::forward<valueU>(v));
302297
SN_ASSERT(c.front().is_defined_leaf());
303-
304-
return &c.front();
305298
}
306299

307300
// remove leaf, key must exist
@@ -359,12 +352,12 @@ SN_TYPE_PAR_DEF class sharing_nodet
359352
return nullptr;
360353
}
361354

362-
typename d_it::innert *add_child(const std::size_t n)
355+
typename d_it::innert &add_child(const std::size_t n)
363356
{
364357
SN_ASSERT(is_internal()); // empty() is allowed
365358

366359
to_mapt &m = get_to_map();
367-
return &m[n];
360+
return m[n];
368361
}
369362

370363
void remove_child(const std::size_t n)

unit/util/sharing_node.cpp

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -173,71 +173,6 @@ TEST_CASE("Sharing node", "[core][util]")
173173

174174
REQUIRE(i.get_to_map().empty());
175175
REQUIRE(ci.find_child(0) == nullptr);
176-
177-
innert *p;
178-
179-
p = i.add_child(1);
180-
181-
REQUIRE(p != nullptr);
182176
}
183177
}
184-
185-
SECTION("Combined")
186-
{
187-
typedef sharing_nodet<int, int> leaft;
188-
typedef sharing_nodet<int, int> innert;
189-
190-
innert map;
191-
192-
REQUIRE(map.empty());
193-
194-
innert *ip;
195-
innert *cp;
196-
leaft *lp;
197-
198-
// Add 0 -> 0 -> (0, 1)
199-
200-
ip = &map;
201-
202-
ip = ip->add_child(0);
203-
REQUIRE(ip != nullptr);
204-
205-
cp = ip->add_child(0);
206-
REQUIRE(cp != nullptr);
207-
208-
lp = cp->place_leaf(0, 1);
209-
REQUIRE(lp != nullptr);
210-
211-
// Add 1 -> 2 -> (3, 4)
212-
213-
ip = &map;
214-
215-
ip = ip->add_child(1);
216-
REQUIRE(ip != nullptr);
217-
218-
cp = ip->add_child(2);
219-
REQUIRE(cp != nullptr);
220-
221-
lp = cp->place_leaf(3, 4);
222-
REQUIRE(lp != nullptr);
223-
224-
// Add 1 -> 3 -> (4, 5)
225-
226-
ip = &map;
227-
228-
ip = ip->add_child(1);
229-
REQUIRE(ip != nullptr);
230-
231-
cp = ip->add_child(3);
232-
REQUIRE(cp != nullptr);
233-
234-
lp = cp->place_leaf(4, 5);
235-
REQUIRE(lp != nullptr);
236-
237-
// Copy
238-
239-
innert map2(map);
240-
241-
REQUIRE(map2.shares_with(map));
242-
}
243178
}

0 commit comments

Comments
 (0)