#pragma once #include #include "StarFlatHashTable.hpp" #include "StarHash.hpp" namespace Star { template , typename Equals = std::equal_to, typename Allocator = std::allocator> class FlatHashMap { public: typedef Key key_type; typedef Mapped mapped_type; typedef pair 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: typedef pair TableValue; struct GetKey { key_type const& operator()(TableValue const& value) const; }; typedef FlatHashTable::template rebind_alloc> Table; public: struct const_iterator { typedef std::forward_iterator_tag iterator_category; typedef typename FlatHashMap::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 FlatHashMap::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; }; FlatHashMap(); explicit FlatHashMap(size_t bucketCount, hasher const& hash = hasher(), key_equal const& equal = key_equal(), allocator_type const& alloc = allocator_type()); FlatHashMap(size_t bucketCount, allocator_type const& alloc); FlatHashMap(size_t bucketCount, hasher const& hash, allocator_type const& alloc); explicit FlatHashMap(allocator_type const& alloc); template FlatHashMap(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 FlatHashMap(InputIt first, InputIt last, size_t bucketCount, allocator_type const& alloc); template FlatHashMap(InputIt first, InputIt last, size_t bucketCount, hasher const& hash, allocator_type const& alloc); FlatHashMap(FlatHashMap const& other); FlatHashMap(FlatHashMap const& other, allocator_type const& alloc); FlatHashMap(FlatHashMap&& other); FlatHashMap(FlatHashMap&& other, allocator_type const& alloc); FlatHashMap(initializer_list init, size_t bucketCount = 0, hasher const& hash = hasher(), key_equal const& equal = key_equal(), allocator_type const& alloc = allocator_type()); FlatHashMap(initializer_list init, size_t bucketCount, allocator_type const& alloc); FlatHashMap(initializer_list init, size_t bucketCount, hasher const& hash, allocator_type const& alloc); FlatHashMap& operator=(FlatHashMap const& other); FlatHashMap& operator=(FlatHashMap&& other); FlatHashMap& 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); template ::value>::type> pair insert(T&& value); iterator insert(const_iterator hint, value_type const& value); template ::value>::type> iterator insert(const_iterator hint, T&& 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); mapped_type& at(key_type const& key); mapped_type const& at(key_type const& key) const; mapped_type& operator[](key_type const& key); mapped_type& operator[](key_type&& 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==(FlatHashMap const& rhs) const; bool operator!=(FlatHashMap const& rhs) const; private: Table m_table; }; template auto FlatHashMap::GetKey::operator()(TableValue const& value) const -> key_type const& { return value.first; } template bool FlatHashMap::const_iterator::operator==(const_iterator const& rhs) const { return inner == rhs.inner; } template bool FlatHashMap::const_iterator::operator!=(const_iterator const& rhs) const { return inner != rhs.inner; } template auto FlatHashMap::const_iterator::operator++() -> const_iterator& { ++inner; return *this; } template auto FlatHashMap::const_iterator::operator++(int) -> const_iterator { const_iterator copy(*this); ++*this; return copy; } template auto FlatHashMap::const_iterator::operator*() const -> value_type& { return *operator->(); } template auto FlatHashMap::const_iterator::operator->() const -> value_type* { return (value_type*)(&*inner); } template bool FlatHashMap::iterator::operator==(iterator const& rhs) const { return inner == rhs.inner; } template bool FlatHashMap::iterator::operator!=(iterator const& rhs) const { return inner != rhs.inner; } template auto FlatHashMap::iterator::operator++() -> iterator& { ++inner; return *this; } template auto FlatHashMap::iterator::operator++(int) -> iterator { iterator copy(*this); operator++(); return copy; } template auto FlatHashMap::iterator::operator*() const -> value_type& { return *operator->(); } template auto FlatHashMap::iterator::operator->() const -> value_type* { return (value_type*)(&*inner); } template FlatHashMap::iterator::operator typename FlatHashMap::const_iterator() const { return const_iterator{inner}; } template FlatHashMap::FlatHashMap() : FlatHashMap(0) {} template FlatHashMap::FlatHashMap(size_t bucketCount, hasher const& hash, key_equal const& equal, allocator_type const& alloc) : m_table(bucketCount, GetKey(), hash, equal, alloc) {} template FlatHashMap::FlatHashMap(size_t bucketCount, allocator_type const& alloc) : FlatHashMap(bucketCount, hasher(), key_equal(), alloc) {} template FlatHashMap::FlatHashMap(size_t bucketCount, hasher const& hash, allocator_type const& alloc) : FlatHashMap(bucketCount, hash, key_equal(), alloc) {} template FlatHashMap::FlatHashMap(allocator_type const& alloc) : FlatHashMap(0, hasher(), key_equal(), alloc) {} template template FlatHashMap::FlatHashMap(InputIt first, InputIt last, size_t bucketCount, hasher const& hash, key_equal const& equal, allocator_type const& alloc) : FlatHashMap(bucketCount, hash, equal, alloc) { insert(first, last); } template template FlatHashMap::FlatHashMap(InputIt first, InputIt last, size_t bucketCount, allocator_type const& alloc) : FlatHashMap(first, last, bucketCount, hasher(), key_equal(), alloc) {} template template FlatHashMap::FlatHashMap(InputIt first, InputIt last, size_t bucketCount, hasher const& hash, allocator_type const& alloc) : FlatHashMap(first, last, bucketCount, hash, key_equal(), alloc) {} template FlatHashMap::FlatHashMap(FlatHashMap const& other) : FlatHashMap(other, other.m_table.getAllocator()) {} template FlatHashMap::FlatHashMap(FlatHashMap const& other, allocator_type const& alloc) : FlatHashMap(alloc) { operator=(other); } template FlatHashMap::FlatHashMap(FlatHashMap&& other) : FlatHashMap(std::move(other), other.m_table.getAllocator()) {} template FlatHashMap::FlatHashMap(FlatHashMap&& other, allocator_type const& alloc) : FlatHashMap(alloc) { operator=(std::move(other)); } template FlatHashMap::FlatHashMap(initializer_list init, size_t bucketCount, hasher const& hash, key_equal const& equal, allocator_type const& alloc) : FlatHashMap(bucketCount, hash, equal, alloc) { operator=(init); } template FlatHashMap::FlatHashMap(initializer_list init, size_t bucketCount, allocator_type const& alloc) : FlatHashMap(init, bucketCount, hasher(), key_equal(), alloc) {} template FlatHashMap::FlatHashMap(initializer_list init, size_t bucketCount, hasher const& hash, allocator_type const& alloc) : FlatHashMap(init, bucketCount, hash, key_equal(), alloc) {} template auto FlatHashMap::operator=(FlatHashMap const& other) -> FlatHashMap& { m_table.clear(); m_table.reserve(other.size()); for (auto const& p : other) m_table.insert(p); return *this; } template auto FlatHashMap::operator=(FlatHashMap&& other) -> FlatHashMap& { m_table = std::move(other.m_table); return *this; } template auto FlatHashMap::operator=(initializer_list init) -> FlatHashMap& { clear(); insert(init.begin(), init.end()); return *this; } template auto FlatHashMap::begin() -> iterator { return iterator{m_table.begin()}; } template auto FlatHashMap::end() -> iterator { return iterator{m_table.end()}; } template auto FlatHashMap::begin() const -> const_iterator { return const_iterator{m_table.begin()}; } template auto FlatHashMap::end() const -> const_iterator { return const_iterator{m_table.end()}; } template auto FlatHashMap::cbegin() const -> const_iterator { return begin(); } template auto FlatHashMap::cend() const -> const_iterator { return end(); } template size_t FlatHashMap::empty() const { return m_table.empty(); } template size_t FlatHashMap::size() const { return m_table.size(); } template void FlatHashMap::clear() { m_table.clear(); } template auto FlatHashMap::insert(value_type const& value) -> pair { auto res = m_table.insert(TableValue(value)); return {iterator{res.first}, res.second}; } template template auto FlatHashMap::insert(T&& value) -> pair { auto res = m_table.insert(TableValue(std::forward(value))); return {iterator{res.first}, res.second}; } template auto FlatHashMap::insert(const_iterator hint, value_type const& value) -> iterator { return insert(hint, TableValue(value)); } template template auto FlatHashMap::insert(const_iterator, T&& value) -> iterator { return insert(std::forward(value)).first; } template template void FlatHashMap::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 FlatHashMap::insert(initializer_list init) { insert(init.begin(), init.end()); } template template auto FlatHashMap::emplace(Args&&... args) -> pair { return insert(TableValue(std::forward(args)...)); } template template auto FlatHashMap::emplace_hint(const_iterator hint, Args&&... args) -> iterator { return insert(hint, TableValue(std::forward(args)...)); } template auto FlatHashMap::erase(const_iterator pos) -> iterator { return iterator{m_table.erase(pos.inner)}; } template auto FlatHashMap::erase(const_iterator first, const_iterator last) -> iterator { return iterator{m_table.erase(first.inner, last.inner)}; } template size_t FlatHashMap::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 auto FlatHashMap::at(key_type const& key) -> mapped_type& { auto i = m_table.find(key); if (i == m_table.end()) throw std::out_of_range("no such key in FlatHashMap"); return i->second; } template auto FlatHashMap::at(key_type const& key) const -> mapped_type const& { auto i = m_table.find(key); if (i == m_table.end()) throw std::out_of_range("no such key in FlatHashMap"); return i->second; } template auto FlatHashMap::operator[](key_type const& key) -> mapped_type& { auto i = m_table.find(key); if (i != m_table.end()) return i->second; return m_table.insert({key, mapped_type()}).first->second; } template auto FlatHashMap::operator[](key_type&& key) -> mapped_type& { auto i = m_table.find(key); if (i != m_table.end()) return i->second; return m_table.insert({std::move(key), mapped_type()}).first->second; } template size_t FlatHashMap::count(key_type const& key) const { if (m_table.find(key) != m_table.end()) return 1; else return 0; } template auto FlatHashMap::find(key_type const& key) const -> const_iterator { return const_iterator{m_table.find(key)}; } template auto FlatHashMap::find(key_type const& key) -> iterator { return iterator{m_table.find(key)}; } template auto FlatHashMap::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 FlatHashMap::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 FlatHashMap::reserve(size_t capacity) { m_table.reserve(capacity); } template bool FlatHashMap::operator==(FlatHashMap const& rhs) const { return m_table == rhs.m_table; } template bool FlatHashMap::operator!=(FlatHashMap const& rhs) const { return m_table != rhs.m_table; } }