431a9c00a5
On Linux and macOS, using Clang to compile OpenStarbound produces about 400 MB worth of warnings during the build, making the compiler output unreadable and slowing the build down considerably. 99% of the warnings were unqualified uses of std::move and std::forward, which are now all properly qualified. Fixed a few other minor warnings about non-virtual destructors and some uses of std::move preventing copy elision on temporary objects. Most remaining warnings are now unused parameters.
498 lines
19 KiB
C++
498 lines
19 KiB
C++
#ifndef STAR_FLAT_HASH_SET_HPP
|
|
#define STAR_FLAT_HASH_SET_HPP
|
|
|
|
#include "StarFlatHashTable.hpp"
|
|
#include "StarHash.hpp"
|
|
|
|
namespace Star {
|
|
|
|
template <typename Key, typename Hash = hash<Key>, typename Equals = std::equal_to<Key>, typename Allocator = std::allocator<Key>>
|
|
class FlatHashSet {
|
|
public:
|
|
typedef Key key_type;
|
|
typedef Key value_type;
|
|
typedef size_t size_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef Hash hasher;
|
|
typedef Equals key_equal;
|
|
typedef Allocator allocator_type;
|
|
typedef value_type& reference;
|
|
typedef value_type const& const_reference;
|
|
typedef value_type* pointer;
|
|
typedef value_type const* const_pointer;
|
|
|
|
private:
|
|
struct GetKey {
|
|
key_type const& operator()(value_type const& value) const;
|
|
};
|
|
|
|
typedef FlatHashTable<Key, Key, GetKey, Hash, Equals, Allocator> Table;
|
|
|
|
public:
|
|
struct const_iterator {
|
|
typedef std::forward_iterator_tag iterator_category;
|
|
typedef typename FlatHashSet::value_type const value_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef value_type* pointer;
|
|
typedef value_type& reference;
|
|
|
|
bool operator==(const_iterator const& rhs) const;
|
|
bool operator!=(const_iterator const& rhs) const;
|
|
|
|
const_iterator& operator++();
|
|
const_iterator operator++(int);
|
|
|
|
value_type& operator*() const;
|
|
value_type* operator->() const;
|
|
|
|
typename Table::const_iterator inner;
|
|
};
|
|
|
|
struct iterator {
|
|
typedef std::forward_iterator_tag iterator_category;
|
|
typedef typename FlatHashSet::value_type value_type;
|
|
typedef ptrdiff_t difference_type;
|
|
typedef value_type* pointer;
|
|
typedef value_type& reference;
|
|
|
|
bool operator==(iterator const& rhs) const;
|
|
bool operator!=(iterator const& rhs) const;
|
|
|
|
iterator& operator++();
|
|
iterator operator++(int);
|
|
|
|
value_type& operator*() const;
|
|
value_type* operator->() const;
|
|
|
|
operator const_iterator() const;
|
|
|
|
typename Table::iterator inner;
|
|
};
|
|
|
|
FlatHashSet();
|
|
explicit FlatHashSet(size_t bucketCount, hasher const& hash = hasher(),
|
|
key_equal const& equal = key_equal(), allocator_type const& alloc = allocator_type());
|
|
FlatHashSet(size_t bucketCount, allocator_type const& alloc);
|
|
FlatHashSet(size_t bucketCount, hasher const& hash, allocator_type const& alloc);
|
|
explicit FlatHashSet(allocator_type const& alloc);
|
|
|
|
template <typename InputIt>
|
|
FlatHashSet(InputIt first, InputIt last, size_t bucketCount = 0,
|
|
hasher const& hash = hasher(), key_equal const& equal = key_equal(),
|
|
allocator_type const& alloc = allocator_type());
|
|
template <typename InputIt>
|
|
FlatHashSet(InputIt first, InputIt last, size_t bucketCount, allocator_type const& alloc);
|
|
template <typename InputIt>
|
|
FlatHashSet(InputIt first, InputIt last, size_t bucketCount,
|
|
hasher const& hash, allocator_type const& alloc);
|
|
|
|
FlatHashSet(FlatHashSet const& other);
|
|
FlatHashSet(FlatHashSet const& other, allocator_type const& alloc);
|
|
FlatHashSet(FlatHashSet&& other);
|
|
FlatHashSet(FlatHashSet&& other, allocator_type const& alloc);
|
|
|
|
FlatHashSet(initializer_list<value_type> init, size_t bucketCount = 0,
|
|
hasher const& hash = hasher(), key_equal const& equal = key_equal(),
|
|
allocator_type const& alloc = allocator_type());
|
|
FlatHashSet(initializer_list<value_type> init, size_t bucketCount, allocator_type const& alloc);
|
|
FlatHashSet(initializer_list<value_type> init, size_t bucketCount, hasher const& hash,
|
|
allocator_type const& alloc);
|
|
|
|
FlatHashSet& operator=(FlatHashSet const& other);
|
|
FlatHashSet& operator=(FlatHashSet&& other);
|
|
FlatHashSet& operator=(initializer_list<value_type> init);
|
|
|
|
iterator begin();
|
|
iterator end();
|
|
|
|
const_iterator begin() const;
|
|
const_iterator end() const;
|
|
|
|
const_iterator cbegin() const;
|
|
const_iterator cend() const;
|
|
|
|
size_t empty() const;
|
|
size_t size() const;
|
|
void clear();
|
|
|
|
pair<iterator, bool> insert(value_type const& value);
|
|
pair<iterator, bool> insert(value_type&& value);
|
|
iterator insert(const_iterator hint, value_type const& value);
|
|
iterator insert(const_iterator hint, value_type&& value);
|
|
template <typename InputIt>
|
|
void insert(InputIt first, InputIt last);
|
|
void insert(initializer_list<value_type> init);
|
|
|
|
template <typename... Args>
|
|
pair<iterator, bool> emplace(Args&&... args);
|
|
template <typename... Args>
|
|
iterator emplace_hint(const_iterator hint, Args&&... args);
|
|
|
|
iterator erase(const_iterator pos);
|
|
iterator erase(const_iterator first, const_iterator last);
|
|
size_t erase(key_type const& key);
|
|
|
|
size_t count(key_type const& key) const;
|
|
const_iterator find(key_type const& key) const;
|
|
iterator find(key_type const& key);
|
|
pair<iterator, iterator> equal_range(key_type const& key);
|
|
pair<const_iterator, const_iterator> equal_range(key_type const& key) const;
|
|
|
|
void reserve(size_t capacity);
|
|
|
|
bool operator==(FlatHashSet const& rhs) const;
|
|
bool operator!=(FlatHashSet const& rhs) const;
|
|
|
|
private:
|
|
Table m_table;
|
|
};
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::GetKey::operator()(value_type const& value) const -> key_type const& {
|
|
return value;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
bool FlatHashSet<Key, Hash, Equals, Allocator>::const_iterator::operator==(const_iterator const& rhs) const {
|
|
return inner == rhs.inner;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
bool FlatHashSet<Key, Hash, Equals, Allocator>::const_iterator::operator!=(const_iterator const& rhs) const {
|
|
return inner != rhs.inner;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::const_iterator::operator++() -> const_iterator& {
|
|
++inner;
|
|
return *this;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::const_iterator::operator++(int) -> const_iterator {
|
|
const_iterator copy(*this);
|
|
operator++();
|
|
return copy;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::const_iterator::operator*() const -> value_type& {
|
|
return *inner;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::const_iterator::operator->() const -> value_type* {
|
|
return &operator*();
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
bool FlatHashSet<Key, Hash, Equals, Allocator>::iterator::operator==(iterator const& rhs) const {
|
|
return inner == rhs.inner;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
bool FlatHashSet<Key, Hash, Equals, Allocator>::iterator::operator!=(iterator const& rhs) const {
|
|
return inner != rhs.inner;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::iterator::operator++() -> iterator& {
|
|
++inner;
|
|
return *this;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::iterator::operator++(int) -> iterator {
|
|
iterator copy(*this);
|
|
operator++();
|
|
return copy;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::iterator::operator*() const -> value_type& {
|
|
return *inner;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::iterator::operator->() const -> value_type* {
|
|
return &operator*();
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::iterator::operator typename FlatHashSet<Key, Hash, Equals, Allocator>::const_iterator() const {
|
|
return const_iterator{inner};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet()
|
|
: FlatHashSet(0) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(size_t bucketCount, hasher const& hash,
|
|
key_equal const& equal, allocator_type const& alloc)
|
|
: m_table(bucketCount, GetKey(), hash, equal, alloc) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(size_t bucketCount, allocator_type const& alloc)
|
|
: FlatHashSet(bucketCount, hasher(), key_equal(), alloc) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(size_t bucketCount, hasher const& hash,
|
|
allocator_type const& alloc)
|
|
: FlatHashSet(bucketCount, hash, key_equal(), alloc) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(allocator_type const& alloc)
|
|
: FlatHashSet(0, hasher(), key_equal(), alloc) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
template <typename InputIt>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(InputIt first, InputIt last, size_t bucketCount,
|
|
hasher const& hash, key_equal const& equal, allocator_type const& alloc)
|
|
: FlatHashSet(bucketCount, hash, equal, alloc) {
|
|
insert(first, last);
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
template <typename InputIt>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(InputIt first, InputIt last, size_t bucketCount,
|
|
allocator_type const& alloc)
|
|
: FlatHashSet(first, last, bucketCount, hasher(), key_equal(), alloc) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
template <typename InputIt>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(InputIt first, InputIt last, size_t bucketCount,
|
|
hasher const& hash, allocator_type const& alloc)
|
|
: FlatHashSet(first, last, bucketCount, hash, key_equal(), alloc) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(FlatHashSet const& other)
|
|
: FlatHashSet(other, other.m_table.getAllocator()) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(FlatHashSet const& other, allocator_type const& alloc)
|
|
: FlatHashSet(alloc) {
|
|
operator=(other);
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(FlatHashSet&& other)
|
|
: FlatHashSet(std::move(other), other.m_table.getAllocator()) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(FlatHashSet&& other, allocator_type const& alloc)
|
|
: FlatHashSet(alloc) {
|
|
operator=(std::move(other));
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(initializer_list<value_type> init, size_t bucketCount,
|
|
hasher const& hash, key_equal const& equal, allocator_type const& alloc)
|
|
: FlatHashSet(bucketCount, hash, equal, alloc) {
|
|
operator=(init);
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(initializer_list<value_type> init, size_t bucketCount, allocator_type const& alloc)
|
|
: FlatHashSet(init, bucketCount, hasher(), key_equal(), alloc) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>::FlatHashSet(initializer_list<value_type> init, size_t bucketCount,
|
|
hasher const& hash, allocator_type const& alloc)
|
|
: FlatHashSet(init, bucketCount, hash, key_equal(), alloc) {}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>& FlatHashSet<Key, Hash, Equals, Allocator>::operator=(FlatHashSet const& other) {
|
|
m_table.clear();
|
|
m_table.reserve(other.size());
|
|
for (auto const& p : other)
|
|
m_table.insert(p);
|
|
return *this;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>& FlatHashSet<Key, Hash, Equals, Allocator>::operator=(FlatHashSet&& other) {
|
|
m_table = std::move(other.m_table);
|
|
return *this;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
FlatHashSet<Key, Hash, Equals, Allocator>& FlatHashSet<Key, Hash, Equals, Allocator>::operator=(initializer_list<value_type> init) {
|
|
clear();
|
|
insert(init.begin(), init.end());
|
|
return *this;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::begin() -> iterator {
|
|
return iterator{m_table.begin()};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::end() -> iterator {
|
|
return iterator{m_table.end()};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::begin() const -> const_iterator {
|
|
return const_iterator{m_table.begin()};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::end() const -> const_iterator {
|
|
return const_iterator{m_table.end()};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::cbegin() const -> const_iterator {
|
|
return begin();
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::cend() const -> const_iterator {
|
|
return end();
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
size_t FlatHashSet<Key, Hash, Equals, Allocator>::empty() const {
|
|
return m_table.empty();
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
size_t FlatHashSet<Key, Hash, Equals, Allocator>::size() const {
|
|
return m_table.size();
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
void FlatHashSet<Key, Hash, Equals, Allocator>::clear() {
|
|
m_table.clear();
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::insert(value_type const& value) -> pair<iterator, bool> {
|
|
auto res = m_table.insert(value);
|
|
return {iterator{res.first}, res.second};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::insert(value_type&& value) -> pair<iterator, bool> {
|
|
auto res = m_table.insert(std::move(value));
|
|
return {iterator{res.first}, res.second};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::insert(const_iterator i, value_type const& value) -> iterator {
|
|
return insert(i, value_type(value));
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::insert(const_iterator, value_type&& value) -> iterator {
|
|
return insert(std::move(value)).first;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
template <typename InputIt>
|
|
void FlatHashSet<Key, Hash, Equals, Allocator>::insert(InputIt first, InputIt last) {
|
|
m_table.reserve(m_table.size() + std::distance(first, last));
|
|
for (auto i = first; i != last; ++i)
|
|
m_table.insert(*i);
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
void FlatHashSet<Key, Hash, Equals, Allocator>::insert(initializer_list<value_type> init) {
|
|
insert(init.begin(), init.end());
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
template <typename... Args>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::emplace(Args&&... args) -> pair<iterator, bool> {
|
|
return insert(value_type(forward<Args>(args)...));
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
template <typename... Args>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::emplace_hint(const_iterator i, Args&&... args) -> iterator {
|
|
return insert(i, value_type(forward<Args>(args)...));
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::erase(const_iterator pos) -> iterator {
|
|
return iterator{m_table.erase(pos.inner)};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::erase(const_iterator first, const_iterator last) -> iterator {
|
|
return iterator{m_table.erase(first.inner, last.inner)};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
size_t FlatHashSet<Key, Hash, Equals, Allocator>::erase(key_type const& key) {
|
|
auto i = m_table.find(key);
|
|
if (i != m_table.end()) {
|
|
m_table.erase(i);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
size_t FlatHashSet<Key, Hash, Equals, Allocator>::count(Key const& key) const {
|
|
if (m_table.find(key) != m_table.end())
|
|
return 1;
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::find(key_type const& key) const -> const_iterator {
|
|
return const_iterator{m_table.find(key)};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::find(key_type const& key) -> iterator {
|
|
return iterator{m_table.find(key)};
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::equal_range(key_type const& key) -> pair<iterator, iterator> {
|
|
auto i = find(key);
|
|
if (i != end()) {
|
|
auto j = i;
|
|
++j;
|
|
return {i, j};
|
|
} else {
|
|
return {i, i};
|
|
}
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
auto FlatHashSet<Key, Hash, Equals, Allocator>::equal_range(key_type const& key) const -> pair<const_iterator, const_iterator> {
|
|
auto i = find(key);
|
|
if (i != end()) {
|
|
auto j = i;
|
|
++j;
|
|
return {i, j};
|
|
} else {
|
|
return {i, i};
|
|
}
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
void FlatHashSet<Key, Hash, Equals, Allocator>::reserve(size_t capacity) {
|
|
m_table.reserve(capacity);
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
bool FlatHashSet<Key, Hash, Equals, Allocator>::operator==(FlatHashSet const& rhs) const {
|
|
return m_table == rhs.m_table;
|
|
}
|
|
|
|
template <typename Key, typename Hash, typename Equals, typename Allocator>
|
|
bool FlatHashSet<Key, Hash, Equals, Allocator>::operator!=(FlatHashSet const& rhs) const {
|
|
return m_table != rhs.m_table;
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|