diff --git a/include/boost/unordered/unordered_flat_map.hpp b/include/boost/unordered/unordered_flat_map.hpp index 75cad9a4..fa210436 100644 --- a/include/boost/unordered/unordered_flat_map.hpp +++ b/include/boost/unordered/unordered_flat_map.hpp @@ -1,3 +1,7 @@ +// Copyright (C) 2022 Christian Mazakas +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + #ifndef BOOST_UNORDERED_UNORDERED_FLAT_MAP_HPP_INCLUDED #define BOOST_UNORDERED_UNORDERED_FLAT_MAP_HPP_INCLUDED @@ -11,6 +15,9 @@ #include +#include +#include +#include #include namespace boost { @@ -37,6 +44,8 @@ namespace boost { using value_type = typename map_types::value_type; using size_type = std::size_t; using key_equal = KeyEqual; + using reference = value_type&; + using const_reference = value_type const&; using iterator = typename table_type::iterator; using const_iterator = typename table_type::const_iterator; @@ -48,11 +57,21 @@ namespace boost { const_iterator end() const noexcept { return table_.end(); } const_iterator cend() const noexcept { return table_.cend(); } + /// Capacity + /// + + BOOST_ATTRIBUTE_NODISCARD bool empty() const noexcept + { + return table_.empty(); + } + size_type size() const noexcept { return table_.size(); } /// Modifiers /// + void clear() noexcept { table_.clear(); } + std::pair insert(value_type const& value) { return table_.insert(value); @@ -63,10 +82,109 @@ namespace boost { return table_.insert(std::move(value)); } - size_type count(key_type const& key) const + iterator insert(const_iterator, value_type const& value) { - auto pos = table_.find(key); - return pos != table_.end() ? 1 : 0; + return table_.insert(value).first; + } + + iterator insert(const_iterator, value_type&& value) + { + return table_.insert(std::move(value)).first; + } + + template + typename std::enable_if< + std::is_base_of::value, + void>::type + insert(ForwardIterator first, ForwardIterator last) + { + auto const len = std::distance(first, last); + table_.reserve(len); + for (auto pos = first; pos != last; ++pos) { + table_.insert(*pos); + } + } + + template + typename std::enable_if< + !std::is_base_of::value, + void>::type + insert(InputIterator first, InputIterator last) + { + for (auto pos = first; pos != last; ++pos) { + table_.insert(*pos); + } + } + + void insert(std::initializer_list ilist) + { + this->insert(ilist.begin(), ilist.end()); + } + + template + std::pair insert_or_assign(key_type const& key, M&& obj) + { + auto iter_bool_pair = table_.try_emplace(key, std::forward(obj)); + if (iter_bool_pair.second) { + return iter_bool_pair; + } + iter_bool_pair.first->second = std::forward(obj); + return iter_bool_pair; + } + + template + std::pair insert_or_assign(key_type&& key, M&& obj) + { + auto iter_bool_pair = + table_.try_emplace(std::move(key), std::forward(obj)); + if (iter_bool_pair.second) { + return iter_bool_pair; + } + iter_bool_pair.first->second = std::forward(obj); + return iter_bool_pair; + } + + template + iterator insert_or_assign(const_iterator, key_type const& key, M&& obj) + { + return this->insert_or_assign(key, std::forward(obj)).first; + } + + template + iterator insert_or_assign(const_iterator, key_type&& key, M&& obj) + { + return this->insert_or_assign(std::move(key), std::forward(obj)) + .first; + } + + template std::pair emplace(Args&&... args) + { + return table_.emplace(std::forward(args)...); + } + + template + std::pair try_emplace(key_type const& key, Args&&... args) + { + return table_.try_emplace(key, std::forward(args)...); + } + + template + std::pair try_emplace(key_type&& key, Args&&... args) + { + return table_.try_emplace(std::move(key), std::forward(args)...); + } + + template + iterator try_emplace(const_iterator, key_type const& key, Args&&... args) + { + return table_.try_emplace(key, std::forward(args)...).first; + } + + template + iterator try_emplace(const_iterator, key_type&& key, Args&&... args) + { + return table_.try_emplace(std::move(key), std::forward(args)...) + .first; } void erase(iterator pos) { table_.erase(pos); } @@ -76,6 +194,22 @@ namespace boost { /// Lookup /// + mapped_type& operator[](key_type const& key) + { + return table_.try_emplace(key).first->second; + } + + mapped_type& operator[](key_type&& key) + { + return table_.try_emplace(std::move(key)).first->second; + } + + size_type count(key_type const& key) const + { + auto pos = table_.find(key); + return pos != table_.end() ? 1 : 0; + } + iterator find(key_type const& key) { return table_.find(key); } const_iterator find(key_type const& key) const