#ifndef STAR_FLAT_HASH_SET_HPP #define STAR_FLAT_HASH_SET_HPP #include "StarFlatHashTable.hpp" #include "StarHash.hpp" namespace Star { template , typename Equals = std::equal_to, typename Allocator = std::allocator> 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 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 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 FlatHashSet(InputIt first, InputIt last, size_t bucketCount, allocator_type const& alloc); template 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 init, size_t bucketCount = 0, hasher const& hash = hasher(), key_equal const& equal = key_equal(), allocator_type const& alloc = allocator_type()); FlatHashSet(initializer_list init, size_t bucketCount, allocator_type const& alloc); FlatHashSet(initializer_list init, size_t bucketCount, hasher const& hash, allocator_type const& alloc); FlatHashSet& operator=(FlatHashSet const& other); FlatHashSet& operator=(FlatHashSet&& other); FlatHashSet& operator=(initializer_list 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 insert(value_type const& value); pair insert(value_type&& value); iterator insert(const_iterator hint, value_type const& value); iterator insert(const_iterator hint, value_type&& value); template void insert(InputIt first, InputIt last); void insert(initializer_list init); template pair emplace(Args&&... args); template 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 equal_range(key_type const& key); pair 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 auto FlatHashSet::GetKey::operator()(value_type const& value) const -> key_type const& { return value; } template bool FlatHashSet::const_iterator::operator==(const_iterator const& rhs) const { return inner == rhs.inner; } template bool FlatHashSet::const_iterator::operator!=(const_iterator const& rhs) const { return inner != rhs.inner; } template auto FlatHashSet::const_iterator::operator++() -> const_iterator& { ++inner; return *this; } template auto FlatHashSet::const_iterator::operator++(int) -> const_iterator { const_iterator copy(*this); operator++(); return copy; } template auto FlatHashSet::const_iterator::operator*() const -> value_type& { return *inner; } template auto FlatHashSet::const_iterator::operator->() const -> value_type* { return &operator*(); } template bool FlatHashSet::iterator::operator==(iterator const& rhs) const { return inner == rhs.inner; } template bool FlatHashSet::iterator::operator!=(iterator const& rhs) const { return inner != rhs.inner; } template auto FlatHashSet::iterator::operator++() -> iterator& { ++inner; return *this; } template auto FlatHashSet::iterator::operator++(int) -> iterator { iterator copy(*this); operator++(); return copy; } template auto FlatHashSet::iterator::operator*() const -> value_type& { return *inner; } template auto FlatHashSet::iterator::operator->() const -> value_type* { return &operator*(); } template FlatHashSet::iterator::operator typename FlatHashSet::const_iterator() const { return const_iterator{inner}; } template FlatHashSet::FlatHashSet() : FlatHashSet(0) {} template FlatHashSet::FlatHashSet(size_t bucketCount, hasher const& hash, key_equal const& equal, allocator_type const& alloc) : m_table(bucketCount, GetKey(), hash, equal, alloc) {} template FlatHashSet::FlatHashSet(size_t bucketCount, allocator_type const& alloc) : FlatHashSet(bucketCount, hasher(), key_equal(), alloc) {} template FlatHashSet::FlatHashSet(size_t bucketCount, hasher const& hash, allocator_type const& alloc) : FlatHashSet(bucketCount, hash, key_equal(), alloc) {} template FlatHashSet::FlatHashSet(allocator_type const& alloc) : FlatHashSet(0, hasher(), key_equal(), alloc) {} template template FlatHashSet::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 template FlatHashSet::FlatHashSet(InputIt first, InputIt last, size_t bucketCount, allocator_type const& alloc) : FlatHashSet(first, last, bucketCount, hasher(), key_equal(), alloc) {} template template FlatHashSet::FlatHashSet(InputIt first, InputIt last, size_t bucketCount, hasher const& hash, allocator_type const& alloc) : FlatHashSet(first, last, bucketCount, hash, key_equal(), alloc) {} template FlatHashSet::FlatHashSet(FlatHashSet const& other) : FlatHashSet(other, other.m_table.getAllocator()) {} template FlatHashSet::FlatHashSet(FlatHashSet const& other, allocator_type const& alloc) : FlatHashSet(alloc) { operator=(other); } template FlatHashSet::FlatHashSet(FlatHashSet&& other) : FlatHashSet(std::move(other), other.m_table.getAllocator()) {} template FlatHashSet::FlatHashSet(FlatHashSet&& other, allocator_type const& alloc) : FlatHashSet(alloc) { operator=(std::move(other)); } template FlatHashSet::FlatHashSet(initializer_list init, size_t bucketCount, hasher const& hash, key_equal const& equal, allocator_type const& alloc) : FlatHashSet(bucketCount, hash, equal, alloc) { operator=(init); } template FlatHashSet::FlatHashSet(initializer_list init, size_t bucketCount, allocator_type const& alloc) : FlatHashSet(init, bucketCount, hasher(), key_equal(), alloc) {} template FlatHashSet::FlatHashSet(initializer_list init, size_t bucketCount, hasher const& hash, allocator_type const& alloc) : FlatHashSet(init, bucketCount, hash, key_equal(), alloc) {} template FlatHashSet& FlatHashSet::operator=(FlatHashSet const& other) { m_table.clear(); m_table.reserve(other.size()); for (auto const& p : other) m_table.insert(p); return *this; } template FlatHashSet& FlatHashSet::operator=(FlatHashSet&& other) { m_table = std::move(other.m_table); return *this; } template FlatHashSet& FlatHashSet::operator=(initializer_list init) { clear(); insert(init.begin(), init.end()); return *this; } template auto FlatHashSet::begin() -> iterator { return iterator{m_table.begin()}; } template auto FlatHashSet::end() -> iterator { return iterator{m_table.end()}; } template auto FlatHashSet::begin() const -> const_iterator { return const_iterator{m_table.begin()}; } template auto FlatHashSet::end() const -> const_iterator { return const_iterator{m_table.end()}; } template auto FlatHashSet::cbegin() const -> const_iterator { return begin(); } template auto FlatHashSet::cend() const -> const_iterator { return end(); } template size_t FlatHashSet::empty() const { return m_table.empty(); } template size_t FlatHashSet::size() const { return m_table.size(); } template void FlatHashSet::clear() { m_table.clear(); } template auto FlatHashSet::insert(value_type const& value) -> pair { auto res = m_table.insert(value); return {iterator{res.first}, res.second}; } template auto FlatHashSet::insert(value_type&& value) -> pair { auto res = m_table.insert(std::move(value)); return {iterator{res.first}, res.second}; } template auto FlatHashSet::insert(const_iterator i, value_type const& value) -> iterator { return insert(i, value_type(value)); } template auto FlatHashSet::insert(const_iterator, value_type&& value) -> iterator { return insert(std::move(value)).first; } template template void FlatHashSet::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 void FlatHashSet::insert(initializer_list init) { insert(init.begin(), init.end()); } template template auto FlatHashSet::emplace(Args&&... args) -> pair { return insert(value_type(forward(args)...)); } template template auto FlatHashSet::emplace_hint(const_iterator i, Args&&... args) -> iterator { return insert(i, value_type(forward(args)...)); } template auto FlatHashSet::erase(const_iterator pos) -> iterator { return iterator{m_table.erase(pos.inner)}; } template auto FlatHashSet::erase(const_iterator first, const_iterator last) -> iterator { return iterator{m_table.erase(first.inner, last.inner)}; } template size_t FlatHashSet::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 size_t FlatHashSet::count(Key const& key) const { if (m_table.find(key) != m_table.end()) return 1; else return 0; } template auto FlatHashSet::find(key_type const& key) const -> const_iterator { return const_iterator{m_table.find(key)}; } template auto FlatHashSet::find(key_type const& key) -> iterator { return iterator{m_table.find(key)}; } template auto FlatHashSet::equal_range(key_type const& key) -> pair { auto i = find(key); if (i != end()) { auto j = i; ++j; return {i, j}; } else { return {i, i}; } } template auto FlatHashSet::equal_range(key_type const& key) const -> pair { auto i = find(key); if (i != end()) { auto j = i; ++j; return {i, j}; } else { return {i, i}; } } template void FlatHashSet::reserve(size_t capacity) { m_table.reserve(capacity); } template bool FlatHashSet::operator==(FlatHashSet const& rhs) const { return m_table == rhs.m_table; } template bool FlatHashSet::operator!=(FlatHashSet const& rhs) const { return m_table != rhs.m_table; } } #endif