Skip to content

Commit 85f5713

Browse files
committed
Add a slot_map::partition(Pred) member function.
Just like the standard `std::partition` algorithm, this member function reorders the slot_map's elements in such a way that all elements for which the predicate `pred` returns `true` precede the elements for which `pred` returns `false`. The relative order of the elements is not preserved. The function returns an iterator to the first element of the second group (which may be `end()`, in the case that all elements belong to the first group). Addresses part of #131, although I'm not sure whether this really addresses whatever use case @p-groarke is thinking of.
1 parent 5c875e3 commit 85f5713

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

SG14/slot_map.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,40 @@ class slot_map
278278
return 1;
279279
}
280280

281+
template<class Pred>
282+
constexpr iterator partition(const Pred& pred) {
283+
iterator it = this->begin();
284+
iterator jt = this->end();
285+
if (it == jt) return it;
286+
while (true) {
287+
--jt;
288+
if (it == jt) return it;
289+
while (pred(*it)) {
290+
++it;
291+
if (it == jt) return it;
292+
}
293+
while (!pred(*jt)) {
294+
--jt;
295+
if (it == jt) return it;
296+
}
297+
// Swap *it and *jt in the underlying container,
298+
// but then fix up their keys so they don't appear to move.
299+
auto it_value_index = std::distance(values_.begin(), it);
300+
auto it_reversemap_iter = std::next(reverse_map_.begin(), it_value_index);
301+
auto it_slot_iter = std::next(slots_.begin(), *it_reversemap_iter);
302+
auto jt_value_index = std::distance(values_.begin(), jt);
303+
auto jt_reversemap_iter = std::next(reverse_map_.begin(), jt_value_index);
304+
auto jt_slot_iter = std::next(slots_.begin(), *jt_reversemap_iter);
305+
306+
using std::swap;
307+
swap(*it, *jt);
308+
swap(*it_slot_iter, *jt_slot_iter);
309+
swap(*it_reversemap_iter, *jt_reversemap_iter);
310+
++it;
311+
if (it == jt) return it;
312+
}
313+
}
314+
281315
// clear() has O(n) time complexity and O(1) space complexity.
282316
// It also has semantics differing from erase(begin(), end())
283317
// in that it also resets the generation counter of every slot

SG14_test/slot_map_test.cpp

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,39 @@ static void EraseRangeTest()
278278
}
279279
}
280280

281+
template<class SM>
282+
static void PartitionTest()
283+
{
284+
using T = typename SM::mapped_type;
285+
SM sm;
286+
auto key3 = sm.insert(Monad<T>::from_value(3));
287+
auto key1 = sm.insert(Monad<T>::from_value(1));
288+
auto key4 = sm.insert(Monad<T>::from_value(4));
289+
auto key5 = sm.insert(Monad<T>::from_value(5));
290+
auto key9 = sm.insert(Monad<T>::from_value(9));
291+
auto key2 = sm.insert(Monad<T>::from_value(2));
292+
auto key6 = sm.insert(Monad<T>::from_value(6));
293+
294+
auto pivot = sm.partition([](const auto& elt) {
295+
return Monad<T>::value_of(elt) >= 5;
296+
});
297+
298+
for (auto it = sm.begin(); it != pivot; ++it) {
299+
assert(Monad<T>::value_of(*it) >= 5);
300+
}
301+
for (auto it = pivot; it != sm.end(); ++it) {
302+
assert(Monad<T>::value_of(*it) < 5);
303+
}
304+
305+
assert(Monad<T>::value_of(*sm.find(key3)) == 3);
306+
assert(Monad<T>::value_of(*sm.find(key1)) == 1);
307+
assert(Monad<T>::value_of(*sm.find(key4)) == 4);
308+
assert(Monad<T>::value_of(*sm.find(key5)) == 5);
309+
assert(Monad<T>::value_of(*sm.find(key9)) == 9);
310+
assert(Monad<T>::value_of(*sm.find(key2)) == 2);
311+
assert(Monad<T>::value_of(*sm.find(key6)) == 6);
312+
}
313+
281314
template<class SM>
282315
static void ReserveTest()
283316
{
@@ -430,6 +463,7 @@ void sg14_test::slot_map_test()
430463
InsertEraseStressTest<slot_map_1>([i=3]() mutable { return ++i; });
431464
EraseInLoopTest<slot_map_1>();
432465
EraseRangeTest<slot_map_1>();
466+
PartitionTest<slot_map_1>();
433467
ReserveTest<slot_map_1>();
434468
VerifyCapacityExists<slot_map_1>(true);
435469

@@ -440,6 +474,7 @@ void sg14_test::slot_map_test()
440474
InsertEraseStressTest<slot_map_2>([i=5]() mutable { return ++i; });
441475
EraseInLoopTest<slot_map_2>();
442476
EraseRangeTest<slot_map_2>();
477+
PartitionTest<slot_map_2>();
443478
ReserveTest<slot_map_2>();
444479
VerifyCapacityExists<slot_map_2>(true);
445480

@@ -451,6 +486,7 @@ void sg14_test::slot_map_test()
451486
InsertEraseStressTest<slot_map_3>([i=3]() mutable { return ++i; });
452487
EraseInLoopTest<slot_map_3>();
453488
EraseRangeTest<slot_map_3>();
489+
PartitionTest<slot_map_3>();
454490
ReserveTest<slot_map_3>();
455491
VerifyCapacityExists<slot_map_3>(true);
456492
#endif // __cplusplus >= 201703L
@@ -462,6 +498,7 @@ void sg14_test::slot_map_test()
462498
InsertEraseStressTest<slot_map_4>([i=7]() mutable { return ++i; });
463499
EraseInLoopTest<slot_map_4>();
464500
EraseRangeTest<slot_map_4>();
501+
PartitionTest<slot_map_4>();
465502
ReserveTest<slot_map_4>();
466503
VerifyCapacityExists<slot_map_4>(false);
467504

@@ -472,6 +509,7 @@ void sg14_test::slot_map_test()
472509
InsertEraseStressTest<slot_map_5>([i=7]() mutable { return ++i; });
473510
EraseInLoopTest<slot_map_5>();
474511
EraseRangeTest<slot_map_5>();
512+
PartitionTest<slot_map_5>();
475513
ReserveTest<slot_map_5>();
476514
VerifyCapacityExists<slot_map_5>(false);
477515

@@ -482,6 +520,7 @@ void sg14_test::slot_map_test()
482520
InsertEraseStressTest<slot_map_6>([i=7]() mutable { return ++i; });
483521
EraseInLoopTest<slot_map_6>();
484522
EraseRangeTest<slot_map_6>();
523+
PartitionTest<slot_map_6>();
485524
ReserveTest<slot_map_6>();
486525
VerifyCapacityExists<slot_map_6>(false);
487526

@@ -497,6 +536,7 @@ void sg14_test::slot_map_test()
497536
InsertEraseStressTest<slot_map_7>([i=7]() mutable { return std::make_unique<int>(++i); });
498537
EraseInLoopTest<slot_map_7>();
499538
EraseRangeTest<slot_map_7>();
539+
PartitionTest<slot_map_7>();
500540
ReserveTest<slot_map_7>();
501541
VerifyCapacityExists<slot_map_7>(false);
502542
}

0 commit comments

Comments
 (0)