mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 08:15:59 -10:00
add contains, at_or, and value_or to the SCP maps
Extend the various maps to add a `contains` function, just as several other containers already add `contains`. Also add `at_or` and `value_or` functions to provide ways to query for map values without inserting anything by default, as `operator[]` does. If the map does not contain the key, the default value is returned. Use `at_or` to return a const reference and `value_or` to return a value. (These are only added to `SCP_map` and `SCP_unordered_map`; a `SCP_multimap` equivalent isn't as clearly useful.) Also add Class Template Argument Deduction (CTAD) guides, per existing precedent. And delete function overloads that are intrinsic footguns.
This commit is contained in:
1 parent
6180173fe8
commit
10edea2291
1 file changed
+82
-3
@@ -15,6 +15,7 @@
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
template <typename T>
|
||||
@@ -119,10 +120,54 @@ extern bool lcase_lessthan(const SCP_string& _Left, const SCP_string& _Right);
|
||||
|
||||
|
||||
template <typename T, typename U, typename Less = std::less<T>>
|
||||
using SCP_map = std::map<T, U, Less, std::allocator<std::pair<const T, U>>>;
|
||||
class SCP_map : public std::map<T, U, Less, std::allocator<std::pair<const T, U>>>
|
||||
{
|
||||
public:
|
||||
using std::map<T, U, Less, std::allocator<std::pair<const T, U>>>::map; // inherit all constructors
|
||||
|
||||
bool contains(const T& key) const
|
||||
{
|
||||
return this->find(key) != this->end();
|
||||
}
|
||||
|
||||
// returns a copy of the value at the key, or a copy of default_value if the key is not present;
|
||||
// mirrors std::optional::value_or, and accepts any default that is convertible to the mapped type
|
||||
template <typename V = U>
|
||||
U value_or(const T& key, V&& default_value) const
|
||||
{
|
||||
auto it = this->find(key);
|
||||
return (it != this->end()) ? it->second : static_cast<U>(std::forward<V>(default_value));
|
||||
}
|
||||
|
||||
// returns a reference to the value at the key, or to default_value if the key is not present;
|
||||
// the map and default_value must both outlive the returned reference (use value_or otherwise)
|
||||
const U& at_or(const T& key, const U& default_value) const&
|
||||
{
|
||||
auto it = this->find(key);
|
||||
return (it != this->end()) ? it->second : default_value;
|
||||
}
|
||||
|
||||
// deleted to prevent returning a reference to a temporary default, which would dangle
|
||||
const U& at_or(const T& key, const U&& default_value) const& = delete;
|
||||
|
||||
// deleted to prevent returning a reference into a temporary map, which would dangle
|
||||
const U& at_or(const T& key, const U& default_value) && = delete;
|
||||
const U& at_or(const T& key, const U& default_value) const&& = delete;
|
||||
};
|
||||
template<typename T, typename U> SCP_map(std::initializer_list<std::pair<T, U>>) -> SCP_map<T, U>;
|
||||
|
||||
template <typename T, typename U, typename Less = std::less<T>>
|
||||
using SCP_multimap = std::multimap<T, U, Less, std::allocator<std::pair<const T, U>>>;
|
||||
class SCP_multimap : public std::multimap<T, U, Less, std::allocator<std::pair<const T, U>>>
|
||||
{
|
||||
public:
|
||||
using std::multimap<T, U, Less, std::allocator<std::pair<const T, U>>>::multimap; // inherit all constructors
|
||||
|
||||
bool contains(const T& key) const
|
||||
{
|
||||
return this->find(key) != this->end();
|
||||
}
|
||||
};
|
||||
template<typename T, typename U> SCP_multimap(std::initializer_list<std::pair<T, U>>) -> SCP_multimap<T, U>;
|
||||
|
||||
template <typename T>
|
||||
using SCP_queue = std::queue<T, std::deque<T, std::allocator<T>>>;
|
||||
@@ -184,7 +229,41 @@ struct SCP_string_lcase_less_than {
|
||||
};
|
||||
|
||||
template <typename Key, typename T, typename Hash = SCP_hash<Key>, typename KeyEqual = std::equal_to<Key>>
|
||||
using SCP_unordered_map = std::unordered_map<Key, T, Hash, KeyEqual, std::allocator<std::pair<const Key, T>>>;
|
||||
class SCP_unordered_map : public std::unordered_map<Key, T, Hash, KeyEqual, std::allocator<std::pair<const Key, T>>>
|
||||
{
|
||||
public:
|
||||
using std::unordered_map<Key, T, Hash, KeyEqual, std::allocator<std::pair<const Key, T>>>::unordered_map; // inherit all constructors
|
||||
|
||||
bool contains(const Key& key) const
|
||||
{
|
||||
return this->find(key) != this->end();
|
||||
}
|
||||
|
||||
// returns a copy of the value at the key, or a copy of default_value if the key is not present;
|
||||
// mirrors std::optional::value_or, and accepts any default that is convertible to the mapped type
|
||||
template <typename V = T>
|
||||
T value_or(const Key& key, V&& default_value) const
|
||||
{
|
||||
auto it = this->find(key);
|
||||
return (it != this->end()) ? it->second : static_cast<T>(std::forward<V>(default_value));
|
||||
}
|
||||
|
||||
// returns a reference to the value at the key, or to default_value if the key is not present;
|
||||
// the map and default_value must both outlive the returned reference (use value_or otherwise)
|
||||
const T& at_or(const Key& key, const T& default_value) const&
|
||||
{
|
||||
auto it = this->find(key);
|
||||
return (it != this->end()) ? it->second : default_value;
|
||||
}
|
||||
|
||||
// deleted to prevent returning a reference to a temporary default, which would dangle
|
||||
const T& at_or(const Key& key, const T&& default_value) const& = delete;
|
||||
|
||||
// deleted to prevent returning a reference into a temporary map, which would dangle
|
||||
const T& at_or(const Key& key, const T& default_value) && = delete;
|
||||
const T& at_or(const Key& key, const T& default_value) const&& = delete;
|
||||
};
|
||||
template<typename Key, typename T> SCP_unordered_map(std::initializer_list<std::pair<Key, T>>) -> SCP_unordered_map<Key, T>;
|
||||
|
||||
template <typename Key, typename Hash = SCP_hash<Key>, typename KeyEqual = std::equal_to<Key>>
|
||||
class SCP_unordered_set : public std::unordered_set<Key, Hash, KeyEqual, std::allocator<Key>>
|
||||
|
||||
Reference in new issue
Block a user