diff options
author | Jacques Lucke <mail@jlucke.com> | 2019-09-14 13:11:14 +0300 |
---|---|---|
committer | Jacques Lucke <mail@jlucke.com> | 2019-09-14 13:11:14 +0300 |
commit | 79e1165bd7488850e896112c2b0f8bf1e6b25db9 (patch) | |
tree | 1cb20163e2aaff754e295360457b1f15428eca25 /source/blender | |
parent | ca76ecfa0ee1153677d8c89149000c7e9a5814d6 (diff) |
BLI: Improve forwarding semantics of some data structures
This makes it possible to use e.g. `std::unique_ptr` in a map.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenlib/BLI_hash_cxx.h | 7 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_map.h | 205 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_set.h | 80 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_set_vector.h | 62 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_stack_cxx.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_string_map.h | 48 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_vector.h | 4 |
7 files changed, 260 insertions, 148 deletions
diff --git a/source/blender/blenlib/BLI_hash_cxx.h b/source/blender/blenlib/BLI_hash_cxx.h index 78b8ee20b0c..8e7d498a4c8 100644 --- a/source/blender/blenlib/BLI_hash_cxx.h +++ b/source/blender/blenlib/BLI_hash_cxx.h @@ -89,6 +89,13 @@ template<typename T> struct DefaultHash<T *> { } }; +template<typename T> struct DefaultHash<std::unique_ptr<T>> { + uint32_t operator()(const std::unique_ptr<T> &value) const + { + return DefaultHash<T *>{}(value.get()); + } +}; + template<typename T1, typename T2> struct DefaultHash<std::pair<T1, T2>> { uint32_t operator()(const std::pair<T1, T2> &value) const { diff --git a/source/blender/blenlib/BLI_map.h b/source/blender/blenlib/BLI_map.h index a5358304c77..3dc51a79be9 100644 --- a/source/blender/blenlib/BLI_map.h +++ b/source/blender/blenlib/BLI_map.h @@ -142,20 +142,13 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> return (ValueT *)(m_values + offset * sizeof(ValueT)); } - void copy_in(uint offset, const KeyT &key, const ValueT &value) + template<typename ForwardKeyT, typename ForwardValueT> + void store(uint offset, ForwardKeyT &&key, ForwardValueT &&value) { BLI_assert(m_status[offset] != IS_SET); m_status[offset] = IS_SET; - new (this->key(offset)) KeyT(key); - new (this->value(offset)) ValueT(value); - } - - void move_in(uint offset, KeyT &key, ValueT &value) - { - BLI_assert(m_status[offset] != IS_SET); - m_status[offset] = IS_SET; - new (this->key(offset)) KeyT(std::move(key)); - new (this->value(offset)) ValueT(std::move(value)); + new (this->key(offset)) KeyT(std::forward<ForwardKeyT>(key)); + new (this->value(offset)) ValueT(std::forward<ForwardValueT>(value)); } void set_dummy(uint offset) @@ -199,17 +192,19 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> */ void add_new(const KeyT &key, const ValueT &value) { - BLI_assert(!this->contains(key)); - this->ensure_can_add(); - - ITER_SLOTS_BEGIN (key, m_array, , item, offset) { - if (item.is_empty(offset)) { - item.copy_in(offset, key, value); - m_array.update__empty_to_set(); - return; - } - } - ITER_SLOTS_END(offset); + this->add_new__impl(key, value); + } + void add_new(const KeyT &key, ValueT &&value) + { + this->add_new__impl(key, std::move(value)); + } + void add_new(KeyT &&key, const ValueT &value) + { + this->add_new__impl(std::move(key), value); + } + void add_new(KeyT &&key, ValueT &&value) + { + this->add_new__impl(std::move(key), std::move(value)); } /** @@ -218,19 +213,19 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> */ bool add(const KeyT &key, const ValueT &value) { - this->ensure_can_add(); - - ITER_SLOTS_BEGIN (key, m_array, , item, offset) { - if (item.is_empty(offset)) { - item.copy_in(offset, key, value); - m_array.update__empty_to_set(); - return true; - } - else if (item.has_key(offset, key)) { - return false; - } - } - ITER_SLOTS_END(offset); + return this->add__impl(key, value); + } + bool add(const KeyT &key, ValueT &&value) + { + return this->add__impl(key, std::move(value)); + } + bool add(KeyT &&key, const ValueT &value) + { + return this->add__impl(std::move(key), value); + } + bool add(KeyT &&key, ValueT &&value) + { + return this->add__impl(std::move(key), std::move(value)); } /** @@ -295,20 +290,14 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> const CreateValueF &create_value, const ModifyValueF &modify_value) { - this->ensure_can_add(); - - ITER_SLOTS_BEGIN (key, m_array, , item, offset) { - if (item.is_empty(offset)) { - item.copy_in(offset, key, create_value()); - m_array.update__empty_to_set(); - return true; - } - else if (item.has_key(offset, key)) { - modify_value(*item.value(offset)); - return false; - } - } - ITER_SLOTS_END(offset); + return this->add_or_modify__impl(key, create_value, modify_value); + } + template<typename CreateValueF, typename ModifyValueF> + bool add_or_modify(KeyT &&key, + const CreateValueF &create_value, + const ModifyValueF &modify_value) + { + return this->add_or_modify__impl(std::move(key), create_value, modify_value); } /** @@ -316,8 +305,19 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> */ bool add_override(const KeyT &key, const ValueT &value) { - return this->add_or_modify( - key, [&value]() { return value; }, [&value](ValueT &old_value) { old_value = value; }); + return this->add_override__impl(key, value); + } + bool add_override(const KeyT &key, ValueT &&value) + { + return this->add_override__impl(key, std::move(value)); + } + bool add_override(KeyT &&key, const ValueT &value) + { + return this->add_override__impl(std::move(key), value); + } + bool add_override(KeyT &&key, ValueT &&value) + { + return this->add_override__impl(std::move(key), std::move(value)); } /** @@ -384,19 +384,12 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> template<typename CreateValueF> ValueT &lookup_or_add(const KeyT &key, const CreateValueF &create_value) { - this->ensure_can_add(); - - ITER_SLOTS_BEGIN (key, m_array, , item, offset) { - if (item.is_empty(offset)) { - item.copy_in(offset, key, create_value()); - m_array.update__empty_to_set(); - return *item.value(offset); - } - else if (item.has_key(offset, key)) { - return *item.value(offset); - } - } - ITER_SLOTS_END(offset); + return this->lookup_or_add__impl(key, create_value); + } + template<typename CreateValueF> + ValueT &lookup_or_add(KeyT &&key, const CreateValueF &create_value) + { + return this->lookup_or_add__impl(std::move(key), create_value); } /** @@ -608,12 +601,94 @@ template<typename KeyT, typename ValueT, typename Allocator = GuardedAllocator> { ITER_SLOTS_BEGIN (key, new_array, , item, offset) { if (item.is_empty(offset)) { - item.move_in(offset, key, value); + item.store(offset, std::move(key), std::move(value)); return; } } ITER_SLOTS_END(offset); } + + template<typename ForwardKeyT, typename ForwardValueT> + bool add_override__impl(ForwardKeyT &&key, ForwardValueT &&value) + { + return this->add_or_modify( + std::forward<ForwardKeyT>(key), + [&]() { return std::forward<ForwardValueT>(value); }, + [&](ValueT &old_value) { old_value = std::forward<ForwardValueT>(value); }); + } + + template<typename ForwardKeyT, typename ForwardValueT> + bool add__impl(ForwardKeyT &&key, ForwardValueT &&value) + { + this->ensure_can_add(); + + ITER_SLOTS_BEGIN (key, m_array, , item, offset) { + if (item.is_empty(offset)) { + item.store(offset, std::forward<ForwardKeyT>(key), std::forward<ForwardValueT>(value)); + m_array.update__empty_to_set(); + return true; + } + else if (item.has_key(offset, key)) { + return false; + } + } + ITER_SLOTS_END(offset); + } + + template<typename ForwardKeyT, typename ForwardValueT> + void add_new__impl(ForwardKeyT &&key, ForwardValueT &&value) + { + BLI_assert(!this->contains(key)); + this->ensure_can_add(); + + ITER_SLOTS_BEGIN (key, m_array, , item, offset) { + if (item.is_empty(offset)) { + item.store(offset, std::forward<ForwardKeyT>(key), std::forward<ForwardValueT>(value)); + m_array.update__empty_to_set(); + return; + } + } + ITER_SLOTS_END(offset); + } + + template<typename ForwardKeyT, typename CreateValueF, typename ModifyValueF> + bool add_or_modify__impl(ForwardKeyT &&key, + const CreateValueF &create_value, + const ModifyValueF &modify_value) + { + this->ensure_can_add(); + + ITER_SLOTS_BEGIN (key, m_array, , item, offset) { + if (item.is_empty(offset)) { + item.store(offset, std::forward<ForwardKeyT>(key), create_value()); + m_array.update__empty_to_set(); + return true; + } + else if (item.has_key(offset, key)) { + modify_value(*item.value(offset)); + return false; + } + } + ITER_SLOTS_END(offset); + } + + template<typename ForwardKeyT, typename CreateValueF> + ValueT &lookup_or_add__impl(ForwardKeyT &&key, const CreateValueF &create_value) + { + this->ensure_can_add(); + + ITER_SLOTS_BEGIN (key, m_array, , item, offset) { + if (item.is_empty(offset)) { + item.store(offset, std::forward<ForwardKeyT>(key), create_value()); + m_array.update__empty_to_set(); + return *item.value(offset); + } + else if (item.has_key(offset, key)) { + return *item.value(offset); + } + } + ITER_SLOTS_END(offset); + } }; #undef ITER_SLOTS_BEGIN diff --git a/source/blender/blenlib/BLI_set.h b/source/blender/blenlib/BLI_set.h index feb0574338e..dc101add1a7 100644 --- a/source/blender/blenlib/BLI_set.h +++ b/source/blender/blenlib/BLI_set.h @@ -117,20 +117,12 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { return (T *)(m_values + offset * sizeof(T)); } - void copy_in(uint offset, const T &value) + template<typename ForwardT> void store(uint offset, ForwardT &&value) { BLI_assert(m_status[offset] != IS_SET); m_status[offset] = IS_SET; T *dst = this->value(offset); - new (dst) T(value); - } - - void move_in(uint offset, T &value) - { - BLI_assert(m_status[offset] != IS_SET); - m_status[offset] = IS_SET; - T *dst = this->value(offset); - new (dst) T(std::move(value)); + new (dst) T(std::forward<ForwardT>(value)); } void set_dummy(uint offset) @@ -201,17 +193,11 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { */ void add_new(const T &value) { - BLI_assert(!this->contains(value)); - this->ensure_can_add(); - - ITER_SLOTS_BEGIN (value, m_array, , item, offset) { - if (item.is_empty(offset)) { - item.copy_in(offset, value); - m_array.update__empty_to_set(); - return; - } - } - ITER_SLOTS_END(offset); + this->add_new__impl(value); + } + void add_new(T &&value) + { + this->add_new__impl(std::move(value)); } /** @@ -219,19 +205,11 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { */ bool add(const T &value) { - this->ensure_can_add(); - - ITER_SLOTS_BEGIN (value, m_array, , item, offset) { - if (item.is_empty(offset)) { - item.copy_in(offset, value); - m_array.update__empty_to_set(); - return true; - } - else if (item.has_value(offset, value)) { - return false; - } - } - ITER_SLOTS_END(offset); + return this->add__impl(value); + } + bool add(T &&value) + { + return this->add__impl(std::move(value)); } /** @@ -445,7 +423,7 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { { ITER_SLOTS_BEGIN (old_value, new_array, , item, offset) { if (item.is_empty(offset)) { - item.move_in(offset, old_value); + item.store(offset, std::move(old_value)); return; } } @@ -463,6 +441,38 @@ template<typename T, typename Allocator = GuardedAllocator> class Set { } ITER_SLOTS_END(offset); } + + template<typename ForwardT> void add_new__impl(ForwardT &&value) + { + BLI_assert(!this->contains(value)); + this->ensure_can_add(); + + ITER_SLOTS_BEGIN (value, m_array, , item, offset) { + if (item.is_empty(offset)) { + item.store(offset, std::forward<ForwardT>(value)); + m_array.update__empty_to_set(); + return; + } + } + ITER_SLOTS_END(offset); + } + + template<typename ForwardT> bool add__impl(ForwardT &&value) + { + this->ensure_can_add(); + + ITER_SLOTS_BEGIN (value, m_array, , item, offset) { + if (item.is_empty(offset)) { + item.store(offset, std::forward<ForwardT>(value)); + m_array.update__empty_to_set(); + return true; + } + else if (item.has_value(offset, value)) { + return false; + } + } + ITER_SLOTS_END(offset); + } }; #undef ITER_SLOTS_BEGIN diff --git a/source/blender/blenlib/BLI_set_vector.h b/source/blender/blenlib/BLI_set_vector.h index c0b99d568cc..3d5a31e1cce 100644 --- a/source/blender/blenlib/BLI_set_vector.h +++ b/source/blender/blenlib/BLI_set_vector.h @@ -147,15 +147,11 @@ template<typename T, typename Allocator = GuardedAllocator> class SetVector { */ void add_new(const T &value) { - BLI_assert(!this->contains(value)); - this->ensure_can_add(); - ITER_SLOTS_BEGIN (value, m_array, , slot) { - if (slot.is_empty()) { - this->add_new_in_slot(slot, value); - return; - } - } - ITER_SLOTS_END; + this->add_new__impl(value); + } + void add_new(T &&value) + { + this->add_new__impl(std::move(value)); } /** @@ -163,17 +159,11 @@ template<typename T, typename Allocator = GuardedAllocator> class SetVector { */ bool add(const T &value) { - this->ensure_can_add(); - ITER_SLOTS_BEGIN (value, m_array, , slot) { - if (slot.is_empty()) { - this->add_new_in_slot(slot, value); - return true; - } - else if (slot.has_value(value, m_elements)) { - return false; - } - } - ITER_SLOTS_END; + return this->add__impl(value); + } + bool add(T &&value) + { + return this->add__impl(std::move(value)); } /** @@ -332,11 +322,11 @@ template<typename T, typename Allocator = GuardedAllocator> class SetVector { ITER_SLOTS_END; } - void add_new_in_slot(Slot &slot, const T &value) + template<typename ForwardT> void add_new_in_slot(Slot &slot, ForwardT &&value) { uint index = m_elements.size(); slot.set_index(index); - m_elements.append(value); + m_elements.append(std::forward<ForwardT>(value)); m_array.update__empty_to_set(); } @@ -369,6 +359,34 @@ template<typename T, typename Allocator = GuardedAllocator> class SetVector { } ITER_SLOTS_END; } + + template<typename ForwardT> void add_new__impl(ForwardT &&value) + { + BLI_assert(!this->contains(value)); + this->ensure_can_add(); + ITER_SLOTS_BEGIN (value, m_array, , slot) { + if (slot.is_empty()) { + this->add_new_in_slot(slot, std::forward<ForwardT>(value)); + return; + } + } + ITER_SLOTS_END; + } + + template<typename ForwardT> bool add__impl(ForwardT &&value) + { + this->ensure_can_add(); + ITER_SLOTS_BEGIN (value, m_array, , slot) { + if (slot.is_empty()) { + this->add_new_in_slot(slot, std::forward<ForwardT>(value)); + return true; + } + else if (slot.has_value(value, m_elements)) { + return false; + } + } + ITER_SLOTS_END; + } }; #undef ITER_SLOTS_BEGIN diff --git a/source/blender/blenlib/BLI_stack_cxx.h b/source/blender/blenlib/BLI_stack_cxx.h index 4c9f2ed7d44..7915acadfac 100644 --- a/source/blender/blenlib/BLI_stack_cxx.h +++ b/source/blender/blenlib/BLI_stack_cxx.h @@ -73,7 +73,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class St void push(T &&value) { - m_elements.append(std::forward<T>(value)); + m_elements.append(std::move(value)); } /** diff --git a/source/blender/blenlib/BLI_string_map.h b/source/blender/blenlib/BLI_string_map.h index 2daf192f0a7..ba870eb878a 100644 --- a/source/blender/blenlib/BLI_string_map.h +++ b/source/blender/blenlib/BLI_string_map.h @@ -152,20 +152,13 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { return StringRefNull(start, length); } - void move_in(uint offset, uint32_t hash, uint32_t index, T &value) + template<typename ForwardT> + void store(uint offset, uint32_t hash, uint32_t index, ForwardT &&value) { BLI_assert(!this->is_set(offset)); m_hashes[offset] = hash; m_indices[offset] = index; - new (this->value(offset)) T(std::move(value)); - } - - void copy_in(uint offset, uint32_t hash, uint32_t index, const T &value) - { - BLI_assert(!this->is_set(offset)); - m_hashes[offset] = hash; - m_indices[offset] = index; - new (this->value(offset)) T(value); + new (this->value(offset)) T(std::forward<ForwardT>(value)); } }; @@ -189,18 +182,11 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { */ void add_new(StringRef key, const T &value) { - BLI_assert(!this->contains(key)); - this->ensure_can_add(); - uint32_t hash = this->compute_string_hash(key); - ITER_SLOTS_BEGIN (hash, m_array, , item, offset) { - if (item.is_empty(offset)) { - uint32_t index = this->save_key_in_array(key); - item.copy_in(offset, hash, index, value); - m_array.update__empty_to_set(); - return; - } - } - ITER_SLOTS_END(offset); + this->add_new__impl(key, value); + } + void add_new(StringRef key, T &&value) + { + this->add_new__impl(key, std::move(value)); } /** @@ -407,7 +393,23 @@ template<typename T, typename Allocator = GuardedAllocator> class StringMap { { ITER_SLOTS_BEGIN (hash, new_array, , item, offset) { if (item.is_empty(offset)) { - item.move_in(offset, hash, index, value); + item.store(offset, hash, index, std::move(value)); + return; + } + } + ITER_SLOTS_END(offset); + } + + template<typename ForwardT> void add_new__impl(StringRef key, ForwardT &&value) + { + BLI_assert(!this->contains(key)); + this->ensure_can_add(); + uint32_t hash = this->compute_string_hash(key); + ITER_SLOTS_BEGIN (hash, m_array, , item, offset) { + if (item.is_empty(offset)) { + uint32_t index = this->save_key_in_array(key); + item.store(offset, hash, index, std::forward<ForwardT>(value)); + m_array.update__empty_to_set(); return; } } diff --git a/source/blender/blenlib/BLI_vector.h b/source/blender/blenlib/BLI_vector.h index 97357ecd384..c9701dcaa52 100644 --- a/source/blender/blenlib/BLI_vector.h +++ b/source/blender/blenlib/BLI_vector.h @@ -419,7 +419,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve { BLI_assert(!this->empty()); m_end--; - T value = *m_end; + T value = std::move(*m_end); destruct(m_end); UPDATE_VECTOR_SIZE(this); return value; @@ -435,7 +435,7 @@ template<typename T, uint N = 4, typename Allocator = GuardedAllocator> class Ve T *element_to_remove = m_begin + index; m_end--; if (element_to_remove < m_end) { - *element_to_remove = *m_end; + *element_to_remove = std::move(*m_end); } destruct(m_end); UPDATE_VECTOR_SIZE(this); |