BLI: support multiple arguments for value in *_as methods of Map
This allows us to build more complex values in-place in the map. Before those values had to be build separately and then moved into the map. Existing calls to the Map API remain unchanged.
This commit is contained in:
@@ -247,11 +247,11 @@ class Map {
|
|||||||
{
|
{
|
||||||
this->add_new_as(std::move(key), std::move(value));
|
this->add_new_as(std::move(key), std::move(value));
|
||||||
}
|
}
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
void add_new_as(ForwardKey &&key, ForwardValue &&value)
|
void add_new_as(ForwardKey &&key, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
this->add_new__impl(
|
this->add_new__impl(
|
||||||
std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
|
std::forward<ForwardKey>(key), hash_(key), std::forward<ForwardValue>(value)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -277,11 +277,11 @@ class Map {
|
|||||||
{
|
{
|
||||||
return this->add_as(std::move(key), std::move(value));
|
return this->add_as(std::move(key), std::move(value));
|
||||||
}
|
}
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
bool add_as(ForwardKey &&key, ForwardValue &&value)
|
bool add_as(ForwardKey &&key, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
return this->add__impl(
|
return this->add__impl(
|
||||||
std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
|
std::forward<ForwardKey>(key), hash_(key), std::forward<ForwardValue>(value)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -307,11 +307,11 @@ class Map {
|
|||||||
{
|
{
|
||||||
return this->add_overwrite_as(std::move(key), std::move(value));
|
return this->add_overwrite_as(std::move(key), std::move(value));
|
||||||
}
|
}
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
bool add_overwrite_as(ForwardKey &&key, ForwardValue &&value)
|
bool add_overwrite_as(ForwardKey &&key, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
return this->add_overwrite__impl(
|
return this->add_overwrite__impl(
|
||||||
std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
|
std::forward<ForwardKey>(key), hash_(key), std::forward<ForwardValue>(value)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -413,12 +413,12 @@ class Map {
|
|||||||
{
|
{
|
||||||
return this->pop_default_as(key, std::move(default_value));
|
return this->pop_default_as(key, std::move(default_value));
|
||||||
}
|
}
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
Value pop_default_as(const ForwardKey &key, ForwardValue &&default_value)
|
Value pop_default_as(const ForwardKey &key, ForwardValue &&... default_value)
|
||||||
{
|
{
|
||||||
Slot *slot = this->lookup_slot_ptr(key, hash_(key));
|
Slot *slot = this->lookup_slot_ptr(key, hash_(key));
|
||||||
if (slot == nullptr) {
|
if (slot == nullptr) {
|
||||||
return std::forward<ForwardValue>(default_value);
|
return Value(std::forward<ForwardValue>(default_value)...);
|
||||||
}
|
}
|
||||||
Value value = std::move(*slot->value());
|
Value value = std::move(*slot->value());
|
||||||
slot->remove();
|
slot->remove();
|
||||||
@@ -525,15 +525,15 @@ class Map {
|
|||||||
{
|
{
|
||||||
return this->lookup_default_as(key, default_value);
|
return this->lookup_default_as(key, default_value);
|
||||||
}
|
}
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
Value lookup_default_as(const ForwardKey &key, ForwardValue &&default_value) const
|
Value lookup_default_as(const ForwardKey &key, ForwardValue &&... default_value) const
|
||||||
{
|
{
|
||||||
const Value *ptr = this->lookup_ptr_as(key);
|
const Value *ptr = this->lookup_ptr_as(key);
|
||||||
if (ptr != nullptr) {
|
if (ptr != nullptr) {
|
||||||
return *ptr;
|
return *ptr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return std::forward<ForwardValue>(default_value);
|
return Value(std::forward<ForwardValue>(default_value)...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,11 +557,11 @@ class Map {
|
|||||||
{
|
{
|
||||||
return this->lookup_or_add_as(std::move(key), std::move(value));
|
return this->lookup_or_add_as(std::move(key), std::move(value));
|
||||||
}
|
}
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
Value &lookup_or_add_as(ForwardKey &&key, ForwardValue &&value)
|
Value &lookup_or_add_as(ForwardKey &&key, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
return this->lookup_or_add__impl(
|
return this->lookup_or_add__impl(
|
||||||
std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash_(key));
|
std::forward<ForwardKey>(key), hash_(key), std::forward<ForwardValue>(value)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -982,7 +982,7 @@ class Map {
|
|||||||
SLOT_PROBING_BEGIN (ProbingStrategy, hash, new_slot_mask, slot_index) {
|
SLOT_PROBING_BEGIN (ProbingStrategy, hash, new_slot_mask, slot_index) {
|
||||||
Slot &slot = new_slots[slot_index];
|
Slot &slot = new_slots[slot_index];
|
||||||
if (slot.is_empty()) {
|
if (slot.is_empty()) {
|
||||||
slot.occupy(std::move(*old_slot.key()), std::move(*old_slot.value()), hash);
|
slot.occupy(std::move(*old_slot.key()), hash, std::move(*old_slot.value()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -996,8 +996,8 @@ class Map {
|
|||||||
new (this) Map(NoExceptConstructor(), allocator);
|
new (this) Map(NoExceptConstructor(), allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
void add_new__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
|
void add_new__impl(ForwardKey &&key, uint64_t hash, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
BLI_assert(!this->contains_as(key));
|
BLI_assert(!this->contains_as(key));
|
||||||
|
|
||||||
@@ -1005,7 +1005,7 @@ class Map {
|
|||||||
|
|
||||||
MAP_SLOT_PROBING_BEGIN (hash, slot) {
|
MAP_SLOT_PROBING_BEGIN (hash, slot) {
|
||||||
if (slot.is_empty()) {
|
if (slot.is_empty()) {
|
||||||
slot.occupy(std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash);
|
slot.occupy(std::forward<ForwardKey>(key), hash, std::forward<ForwardValue>(value)...);
|
||||||
occupied_and_removed_slots_++;
|
occupied_and_removed_slots_++;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1013,14 +1013,14 @@ class Map {
|
|||||||
MAP_SLOT_PROBING_END();
|
MAP_SLOT_PROBING_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
bool add__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
|
bool add__impl(ForwardKey &&key, uint64_t hash, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
this->ensure_can_add();
|
this->ensure_can_add();
|
||||||
|
|
||||||
MAP_SLOT_PROBING_BEGIN (hash, slot) {
|
MAP_SLOT_PROBING_BEGIN (hash, slot) {
|
||||||
if (slot.is_empty()) {
|
if (slot.is_empty()) {
|
||||||
slot.occupy(std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash);
|
slot.occupy(std::forward<ForwardKey>(key), hash, std::forward<ForwardValue>(value)...);
|
||||||
occupied_and_removed_slots_++;
|
occupied_and_removed_slots_++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1075,7 @@ class Map {
|
|||||||
|
|
||||||
MAP_SLOT_PROBING_BEGIN (hash, slot) {
|
MAP_SLOT_PROBING_BEGIN (hash, slot) {
|
||||||
if (slot.is_empty()) {
|
if (slot.is_empty()) {
|
||||||
slot.occupy(std::forward<ForwardKey>(key), create_value(), hash);
|
slot.occupy(std::forward<ForwardKey>(key), hash, create_value());
|
||||||
occupied_and_removed_slots_++;
|
occupied_and_removed_slots_++;
|
||||||
return *slot.value();
|
return *slot.value();
|
||||||
}
|
}
|
||||||
@@ -1086,14 +1086,14 @@ class Map {
|
|||||||
MAP_SLOT_PROBING_END();
|
MAP_SLOT_PROBING_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
Value &lookup_or_add__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
|
Value &lookup_or_add__impl(ForwardKey &&key, uint64_t hash, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
this->ensure_can_add();
|
this->ensure_can_add();
|
||||||
|
|
||||||
MAP_SLOT_PROBING_BEGIN (hash, slot) {
|
MAP_SLOT_PROBING_BEGIN (hash, slot) {
|
||||||
if (slot.is_empty()) {
|
if (slot.is_empty()) {
|
||||||
slot.occupy(std::forward<ForwardKey>(key), std::forward<ForwardValue>(value), hash);
|
slot.occupy(std::forward<ForwardKey>(key), hash, std::forward<ForwardValue>(value)...);
|
||||||
occupied_and_removed_slots_++;
|
occupied_and_removed_slots_++;
|
||||||
return *slot.value();
|
return *slot.value();
|
||||||
}
|
}
|
||||||
@@ -1104,15 +1104,15 @@ class Map {
|
|||||||
MAP_SLOT_PROBING_END();
|
MAP_SLOT_PROBING_END();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
bool add_overwrite__impl(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
|
bool add_overwrite__impl(ForwardKey &&key, uint64_t hash, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
auto create_func = [&](Value *ptr) {
|
auto create_func = [&](Value *ptr) {
|
||||||
new (static_cast<void *>(ptr)) Value(std::forward<ForwardValue>(value));
|
new (static_cast<void *>(ptr)) Value(std::forward<ForwardValue>(value)...);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
auto modify_func = [&](Value *ptr) {
|
auto modify_func = [&](Value *ptr) {
|
||||||
*ptr = std::forward<ForwardValue>(value);
|
*ptr = Value(std::forward<ForwardValue>(value)...);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
return this->add_or_modify__impl(
|
return this->add_or_modify__impl(
|
||||||
@@ -1221,16 +1221,18 @@ template<typename Key, typename Value> class StdUnorderedMapWrapper {
|
|||||||
map_.reserve(n);
|
map_.reserve(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
void add_new(ForwardKey &&key, ForwardValue &&value)
|
void add_new(ForwardKey &&key, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
map_.insert({std::forward<ForwardKey>(key), std::forward<ForwardValue>(value)});
|
map_.insert({std::forward<ForwardKey>(key), Value(std::forward<ForwardValue>(value)...)});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
bool add(ForwardKey &&key, ForwardValue &&value)
|
bool add(ForwardKey &&key, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
return map_.insert({std::forward<ForwardKey>(key), std::forward<ForwardValue>(value)}).second;
|
return map_
|
||||||
|
.insert({std::forward<ForwardKey>(key), Value(std::forward<ForwardValue>(value)...)})
|
||||||
|
.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool contains(const Key &key) const
|
bool contains(const Key &key) const
|
||||||
|
@@ -195,11 +195,11 @@ template<typename Key, typename Value> class SimpleMapSlot {
|
|||||||
* Change the state of this slot from empty/removed to occupied. The key/value has to be
|
* Change the state of this slot from empty/removed to occupied. The key/value has to be
|
||||||
* constructed by calling the constructor with the given key/value as parameter.
|
* constructed by calling the constructor with the given key/value as parameter.
|
||||||
*/
|
*/
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
void occupy(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
|
void occupy(ForwardKey &&key, uint64_t hash, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
BLI_assert(!this->is_occupied());
|
BLI_assert(!this->is_occupied());
|
||||||
new (&value_buffer_) Value(std::forward<ForwardValue>(value));
|
new (&value_buffer_) Value(std::forward<ForwardValue>(value)...);
|
||||||
this->occupy_no_value(std::forward<ForwardKey>(key), hash);
|
this->occupy_no_value(std::forward<ForwardKey>(key), hash);
|
||||||
state_ = Occupied;
|
state_ = Occupied;
|
||||||
}
|
}
|
||||||
@@ -315,12 +315,12 @@ template<typename Key, typename Value, typename KeyInfo> class IntrusiveMapSlot
|
|||||||
return is_equal(key, key_);
|
return is_equal(key, key_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ForwardKey, typename ForwardValue>
|
template<typename ForwardKey, typename... ForwardValue>
|
||||||
void occupy(ForwardKey &&key, ForwardValue &&value, uint64_t hash)
|
void occupy(ForwardKey &&key, uint64_t hash, ForwardValue &&... value)
|
||||||
{
|
{
|
||||||
BLI_assert(!this->is_occupied());
|
BLI_assert(!this->is_occupied());
|
||||||
BLI_assert(KeyInfo::is_not_empty_or_removed(key));
|
BLI_assert(KeyInfo::is_not_empty_or_removed(key));
|
||||||
new (&value_buffer_) Value(std::forward<ForwardValue>(value));
|
new (&value_buffer_) Value(std::forward<ForwardValue>(value)...);
|
||||||
this->occupy_no_value(std::forward<ForwardKey>(key), hash);
|
this->occupy_no_value(std::forward<ForwardKey>(key), hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -604,6 +604,15 @@ TEST(map, GenericAlgorithms)
|
|||||||
EXPECT_EQ(std::count(map.keys().begin(), map.keys().end(), 7), 1);
|
EXPECT_EQ(std::count(map.keys().begin(), map.keys().end(), 7), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(map, AddAsVariadic)
|
||||||
|
{
|
||||||
|
Map<int, StringRef> map;
|
||||||
|
map.add_as(3, "hello", 2);
|
||||||
|
map.add_as(2, "test", 1);
|
||||||
|
EXPECT_EQ(map.lookup(3), "he");
|
||||||
|
EXPECT_EQ(map.lookup(2), "t");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot.
|
* Set this to 1 to activate the benchmark. It is disabled by default, because it prints a lot.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user