Skip to content

Commit 8dd4a4c

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 70626e2 commit 8dd4a4c

File tree

4 files changed

+47
-117
lines changed

4 files changed

+47
-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: 35 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 container node (containing a single leaf) further down the tree
@@ -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
{
@@ -1086,17 +1086,14 @@ SHARING_MAPT2(, leaft *)::get_leaf_node(const key_type &k)
10861086

10871087
if(ip->is_leaf())
10881088
{
1089-
return ip;
1089+
return *ip;
10901090
}
10911091

10921092
if(ip->is_container())
10931093
{
1094-
return ip->find_leaf(k);
1094+
return *ip->find_leaf(k);
10951095
}
10961096
}
1097-
1098-
UNREACHABLE;
1099-
return nullptr;
11001097
}
11011098

11021099
SHARING_MAPT2(const, leaft *)::get_leaf_node(const key_type &k) const
@@ -1154,15 +1151,15 @@ SHARING_MAPT(void)::erase(const key_type &k)
11541151
{
11551152
std::size_t bit = key & mask;
11561153

1157-
const to_mapt &m = as_const(ip)->get_to_map();
1154+
const to_mapt &m = as_const_ptr(ip)->get_to_map();
11581155

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

1165-
ip = ip->add_child(bit);
1162+
ip = &ip->add_child(bit);
11661163

11671164
PRECONDITION(!ip->empty());
11681165

@@ -1185,7 +1182,7 @@ SHARING_MAPT(void)::erase(const key_type &k)
11851182
if(ip->is_container())
11861183
{
11871184
PRECONDITION(!ip->empty());
1188-
const leaf_listt &ll = as_const(ip)->get_container();
1185+
const leaf_listt &ll = as_const_ptr(ip)->get_container();
11891186
PRECONDITION(!ll.empty());
11901187

11911188
// forward list has one element
@@ -1220,7 +1217,7 @@ ::migrate(
12201217
SM_ASSERT(starting_level < levels - 1);
12211218
SM_ASSERT(inner.is_defined_internal());
12221219

1223-
leaft &leaf = *inner.add_child(bit_last);
1220+
leaft &leaf = inner.add_child(bit_last);
12241221
SM_ASSERT(leaf.is_defined_leaf());
12251222

12261223
std::size_t key_existing = hash()(leaf.get_key());
@@ -1253,19 +1250,19 @@ ::migrate(
12531250
{
12541251
// Place found
12551252

1256-
innert *l1 = ip->add_child(bit_existing);
1257-
SM_ASSERT(l1->empty());
1258-
l1->swap(leaf_kept);
1253+
innert &l1 = ip->add_child(bit_existing);
1254+
SM_ASSERT(l1.empty());
1255+
l1.swap(leaf_kept);
12591256

1260-
innert *l2 = ip->add_child(bit);
1261-
SM_ASSERT(l2->empty());
1262-
l2->make_leaf(k, std::forward<valueU>(m));
1257+
innert &l2 = ip->add_child(bit);
1258+
SM_ASSERT(l2.empty());
1259+
l2.make_leaf(k, std::forward<valueU>(m));
12631260

12641261
return;
12651262
}
12661263

12671264
SM_ASSERT(bit == bit_existing);
1268-
ip = ip->add_child(bit);
1265+
ip = &ip->add_child(bit);
12691266

12701267
key >>= chunk;
12711268
key_existing >>= chunk;
@@ -1307,41 +1304,41 @@ ::insert(const key_type &k, valueU &&m)
13071304
SM_ASSERT(ip->is_internal());
13081305
SM_ASSERT(level == 0 || !ip->empty());
13091306

1310-
innert *child = ip->add_child(bit);
1307+
innert &child = ip->add_child(bit);
13111308

13121309
// Place is unoccupied
1313-
if(child->empty())
1310+
if(child.empty())
13141311
{
13151312
if(level < levels - 1)
13161313
{
13171314
// Create leaf
1318-
child->make_leaf(k, m);
1315+
child.make_leaf(k, m);
13191316
}
13201317
else
13211318
{
13221319
SM_ASSERT(level == levels - 1);
13231320

13241321
// Create container and insert leaf
1325-
child->place_leaf(k, std::forward<valueU>(m));
1322+
child.place_leaf(k, std::forward<valueU>(m));
13261323

1327-
SM_ASSERT(child->is_defined_container());
1324+
SM_ASSERT(child.is_defined_container());
13281325
}
13291326

13301327
num++;
13311328

13321329
return;
13331330
}
13341331

1335-
if(child->is_internal())
1332+
if(child.is_internal())
13361333
{
1337-
ip = child;
1334+
ip = &child;
13381335
key >>= chunk;
13391336
level++;
13401337

13411338
continue;
13421339
}
13431340

1344-
if(child->is_leaf())
1341+
if(child.is_leaf())
13451342
{
13461343
// migrate leaf downwards
13471344
migrate(level, key, bit, *ip, k, std::forward<valueU>(m));
@@ -1351,12 +1348,12 @@ ::insert(const key_type &k, valueU &&m)
13511348
return;
13521349
}
13531350

1354-
if(child->is_container())
1351+
if(child.is_container())
13551352
{
13561353
SM_ASSERT(level == levels - 1);
13571354

13581355
// Add to the container
1359-
child->place_leaf(k, std::forward<valueU>(m));
1356+
child.place_leaf(k, std::forward<valueU>(m));
13601357

13611358
num++;
13621359

@@ -1368,28 +1365,26 @@ ::insert(const key_type &k, valueU &&m)
13681365
SHARING_MAPT4(valueU, void)
13691366
::replace(const key_type &k, valueU &&m)
13701367
{
1371-
leaft *lp = get_leaf_node(k);
1372-
PRECONDITION(lp != nullptr); // key must exist in map
1368+
leaft &lp = get_leaf_node(k);
13731369

13741370
INVARIANT(
1375-
!value_equalt()(as_const(lp)->get_value(), m),
1371+
!value_equalt()(as_const(lp).get_value(), m),
13761372
"values should not be replaced with equal values to maximize sharing");
13771373

1378-
lp->set_value(std::forward<valueU>(m));
1374+
lp.set_value(std::forward<valueU>(m));
13791375
}
13801376

13811377
SHARING_MAPT(void)
13821378
::update(const key_type &k, std::function<void(mapped_type &)> mutator)
13831379
{
1384-
leaft *lp = get_leaf_node(k);
1385-
PRECONDITION(lp != nullptr); // key must exist in map
1380+
leaft &lp = get_leaf_node(k);
13861381

1387-
value_comparatort comparator(as_const(lp)->get_value());
1382+
value_comparatort comparator(as_const(lp).get_value());
13881383

1389-
lp->mutate_value(mutator);
1384+
lp.mutate_value(mutator);
13901385

13911386
INVARIANT(
1392-
!comparator(as_const(lp)->get_value()),
1387+
!comparator(as_const(lp).get_value()),
13931388
"sharing_mapt::update should make some change. Consider using read-only "
13941389
"method to check if an update is needed beforehand");
13951390
}

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
#define SN_PTR_TYPE_ARGS \
6263
d_internalt<SN_TYPE_ARGS>, d_containert<SN_TYPE_ARGS>, d_leaft<SN_TYPE_ARGS>
6364

64-
template <class T>
65-
const T *as_const(T *t)
66-
{
67-
return t;
68-
}
69-
7065
// Inner nodes (internal nodes or container nodes)
7166

7267
typedef small_shared_n_way_pointee_baset<3, unsigned> d_baset;
@@ -291,19 +286,17 @@ SN_TYPE_PAR_DEF class sharing_nodet
291286

292287
// add leaf, key must not exist yet
293288
template <class valueU>
294-
leaft *place_leaf(const keyT &k, valueU &&v)
289+
void place_leaf(const keyT &k, valueU &&v)
295290
{
296291
SN_ASSERT(is_container()); // empty() is allowed
297292

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

302297
leaf_listt &c = get_container();
303298
c.emplace_front(k, std::forward<valueU>(v));
304299
SN_ASSERT(c.front().is_defined_leaf());
305-
306-
return &c.front();
307300
}
308301

309302
// remove leaf, key must exist
@@ -361,12 +354,12 @@ SN_TYPE_PAR_DEF class sharing_nodet
361354
return nullptr;
362355
}
363356

364-
typename d_it::innert *add_child(const std::size_t n)
357+
typename d_it::innert &add_child(const std::size_t n)
365358
{
366359
SN_ASSERT(is_internal()); // empty() is allowed
367360

368361
to_mapt &m = get_to_map();
369-
return &m[n];
362+
return m[n];
370363
}
371364

372365
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
@@ -178,71 +178,6 @@ TEST_CASE("Sharing node", "[core][util]")
178178

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

0 commit comments

Comments
 (0)