BLI: add Map.pop_try method
I found this pattern in depsgraph code more than once.
This commit is contained in:
parent
75ce20a000
commit
a71f073dfb
|
@ -73,6 +73,7 @@
|
|||
#include "BLI_hash.hh"
|
||||
#include "BLI_hash_tables.hh"
|
||||
#include "BLI_map_slots.hh"
|
||||
#include "BLI_optional.hh"
|
||||
#include "BLI_probing_strategies.hh"
|
||||
|
||||
namespace blender {
|
||||
|
@ -387,6 +388,23 @@ class Map {
|
|||
return this->pop__impl(key, m_hash(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value that is stored for the given key and remove it from the map. If the key is not
|
||||
* in the map, a value-less optional is returned.
|
||||
*/
|
||||
Optional<Value> pop_try(const Key &key)
|
||||
{
|
||||
return this->pop_try_as(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `pop_try`, but accepts other key types that are supported by the hash function.
|
||||
*/
|
||||
template<typename ForwardKey> Optional<Value> pop_try_as(const ForwardKey &key)
|
||||
{
|
||||
return this->pop_try__impl(key, m_hash(key));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method can be used to implement more complex custom behavior without having to do
|
||||
* multiple lookups
|
||||
|
@ -1029,6 +1047,22 @@ class Map {
|
|||
MAP_SLOT_PROBING_END();
|
||||
}
|
||||
|
||||
template<typename ForwardKey> Optional<Value> pop_try__impl(const ForwardKey &key, uint32_t hash)
|
||||
{
|
||||
MAP_SLOT_PROBING_BEGIN (hash, slot) {
|
||||
if (slot.contains(key, m_is_equal, hash)) {
|
||||
Optional<Value> value = *slot.value();
|
||||
slot.remove();
|
||||
m_removed_slots++;
|
||||
return value;
|
||||
}
|
||||
if (slot.is_empty()) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
MAP_SLOT_PROBING_END();
|
||||
}
|
||||
|
||||
template<typename ForwardKey, typename CreateValueF, typename ModifyValueF>
|
||||
auto add_or_modify__impl(ForwardKey &&key,
|
||||
const CreateValueF &create_value,
|
||||
|
|
|
@ -82,6 +82,23 @@ TEST(map, PopItem)
|
|||
EXPECT_FALSE(map.contains(1));
|
||||
}
|
||||
|
||||
TEST(map, PopTry)
|
||||
{
|
||||
Map<int, int> map;
|
||||
map.add(1, 5);
|
||||
map.add(2, 7);
|
||||
EXPECT_EQ(map.size(), 2);
|
||||
Optional<int> value = map.pop_try(4);
|
||||
EXPECT_EQ(map.size(), 2);
|
||||
EXPECT_FALSE(value.has_value());
|
||||
value = map.pop_try(2);
|
||||
EXPECT_EQ(map.size(), 1);
|
||||
EXPECT_TRUE(value.has_value());
|
||||
EXPECT_EQ(value.value(), 7);
|
||||
EXPECT_EQ(*map.pop_try(1), 5);
|
||||
EXPECT_EQ(map.size(), 0);
|
||||
}
|
||||
|
||||
TEST(map, PopItemMany)
|
||||
{
|
||||
Map<int, int> map;
|
||||
|
|
Loading…
Reference in New Issue