heterogeneous at, erase, count and equal_range

This commit is contained in:
2019-05-27 18:27:26 +07:00
parent 00d676f998
commit 6eaae5784f
8 changed files with 262 additions and 30 deletions

View File

@@ -265,6 +265,30 @@ namespace flat_hpp
throw std::out_of_range("flat_map::at: key not found");
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
mapped_type&>
at(const K& key) {
const iterator iter = find(key);
if ( iter != end() ) {
return iter->second;
}
throw std::out_of_range("flat_map::at: key not found");
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const mapped_type&>
at(const K& key) const {
const const_iterator iter = find(key);
if ( iter != end() ) {
return iter->second;
}
throw std::out_of_range("flat_map::at: key not found");
}
std::pair<iterator, bool> insert(value_type&& value) {
const iterator iter = lower_bound(value.first);
return iter == end() || this->operator()(value, *iter)
@@ -328,7 +352,18 @@ namespace flat_hpp
}
size_type erase(const key_type& key) {
const iterator iter = find(key);
const const_iterator iter = find(key);
return iter != end()
? (erase(iter), 1)
: 0;
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
erase(const K& key) {
const const_iterator iter = find(key);
return iter != end()
? (erase(iter), 1)
: 0;
@@ -350,6 +385,15 @@ namespace flat_hpp
return iter != end() ? 1 : 0;
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
count(const K& key) const {
const const_iterator iter = find(key);
return iter != end() ? 1 : 0;
}
iterator find(const key_type& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
@@ -396,6 +440,24 @@ namespace flat_hpp
return std::equal_range(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<iterator, iterator>>
equal_range(const K& key) {
const base_type& comp = *this;
return std::equal_range(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<const_iterator, const_iterator>>
equal_range(const K& key) const {
const base_type& comp = *this;
return std::equal_range(begin(), end(), key, comp);
}
iterator lower_bound(const key_type& key) {
const base_type& comp = *this;
return std::lower_bound(begin(), end(), key, comp);

View File

@@ -265,6 +265,30 @@ namespace flat_hpp
throw std::out_of_range("flat_multimap::at: key not found");
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
mapped_type&>
at(const K& key) {
const iterator iter = find(key);
if ( iter != end() ) {
return iter->second;
}
throw std::out_of_range("flat_multimap::at: key not found");
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const mapped_type&>
at(const K& key) const {
const const_iterator iter = find(key);
if ( iter != end() ) {
return iter->second;
}
throw std::out_of_range("flat_multimap::at: key not found");
}
iterator insert(value_type&& value) {
const iterator iter = upper_bound(value.first);
return data_.insert(iter, std::move(value));
@@ -330,6 +354,17 @@ namespace flat_hpp
return r;
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
erase(const K& key) {
const auto p = equal_range(key);
size_type r = std::distance(p.first, p.second);
erase(p.first, p.second);
return r;
}
void swap(flat_multimap& other)
noexcept(std::is_nothrow_swappable_v<base_type>
&& std::is_nothrow_swappable_v<container_type>)
@@ -346,6 +381,15 @@ namespace flat_hpp
return std::distance(p.first, p.second);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
count(const K& key) const {
const auto p = equal_range(key);
return std::distance(p.first, p.second);
}
iterator find(const key_type& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
@@ -392,6 +436,24 @@ namespace flat_hpp
return std::equal_range(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<iterator, iterator>>
equal_range(const K& key) {
const base_type& comp = *this;
return std::equal_range(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<const_iterator, const_iterator>>
equal_range(const K& key) const {
const base_type& comp = *this;
return std::equal_range(begin(), end(), key, comp);
}
iterator lower_bound(const key_type& key) {
const base_type& comp = *this;
return std::lower_bound(begin(), end(), key, comp);

View File

@@ -281,6 +281,17 @@ namespace flat_hpp
return r;
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
erase(const K& key) {
const auto p = equal_range(key);
size_type r = std::distance(p.first, p.second);
erase(p.first, p.second);
return r;
}
void swap(flat_multiset& other)
noexcept(std::is_nothrow_swappable_v<base_type>
&& std::is_nothrow_swappable_v<container_type>)
@@ -297,6 +308,15 @@ namespace flat_hpp
return std::distance(p.first, p.second);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
count(const K& key) const {
const auto p = equal_range(key);
return std::distance(p.first, p.second);
}
iterator find(const key_type& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
@@ -341,6 +361,22 @@ namespace flat_hpp
return std::equal_range(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<iterator, iterator>>
equal_range(const K& key) {
return std::equal_range(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<const_iterator, const_iterator>>
equal_range(const K& key) const {
return std::equal_range(begin(), end(), key, key_comp());
}
iterator lower_bound(const key_type& key) {
return std::lower_bound(begin(), end(), key, key_comp());
}

View File

@@ -279,7 +279,18 @@ namespace flat_hpp
}
size_type erase(const key_type& key) {
const iterator iter = find(key);
const const_iterator iter = find(key);
return iter != end()
? (erase(iter), 1)
: 0;
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
erase(const K& key) {
const const_iterator iter = find(key);
return iter != end()
? (erase(iter), 1)
: 0;
@@ -301,6 +312,15 @@ namespace flat_hpp
return iter != end() ? 1 : 0;
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
count(const K& key) const {
const const_iterator iter = find(key);
return iter != end() ? 1 : 0;
}
iterator find(const key_type& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
@@ -345,6 +365,22 @@ namespace flat_hpp
return std::equal_range(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<iterator, iterator>>
equal_range(const K& key) {
return std::equal_range(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<const_iterator, const_iterator>>
equal_range(const K& key) const {
return std::equal_range(begin(), end(), key, key_comp());
}
iterator lower_bound(const key_type& key) {
return std::lower_bound(begin(), end(), key, key_comp());
}

View File

@@ -410,13 +410,23 @@ TEST_CASE("flat_map") {
REQUIRE(my_as_const(s0).lower_bound(-1) == s0.cbegin());
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 3);
}
{
flat_map<std::string, int, std::less<>> s0{{"hello", 42}, {"world", 84}};
REQUIRE(s0.find(std::string_view("hello")) == s0.begin());
REQUIRE(my_as_const(s0).find(std::string_view("world")) == s0.begin() + 1);
REQUIRE(s0.find(std::string_view("42")) == s0.end());
REQUIRE(my_as_const(s0).find(std::string_view("42")) == s0.cend());
}
}
SECTION("heterogeneous") {
flat_map<std::string, int, std::less<>> s0{{"hello", 42}, {"world", 84}};
REQUIRE(s0.find(std::string_view("hello")) == s0.begin());
REQUIRE(my_as_const(s0).find(std::string_view("world")) == s0.begin() + 1);
REQUIRE(s0.find(std::string_view("42")) == s0.end());
REQUIRE(my_as_const(s0).find(std::string_view("42")) == s0.cend());
REQUIRE(my_as_const(s0).count(std::string_view("hello")) == 1);
REQUIRE(my_as_const(s0).count(std::string_view("hello_42")) == 0);
REQUIRE(s0.upper_bound(std::string_view("hello")) == s0.begin() + 1);
REQUIRE(my_as_const(s0).upper_bound(std::string_view("hello")) == s0.begin() + 1);
REQUIRE(s0.erase(std::string_view("hello")) == 1);
REQUIRE(s0.at(std::string_view("world")) == 84);
REQUIRE(my_as_const(s0).at(std::string_view("world")) == 84);
}
SECTION("observers") {
struct my_less {

View File

@@ -412,13 +412,23 @@ TEST_CASE("flat_multimap") {
REQUIRE(my_as_const(s0).lower_bound(-1) == s0.cbegin());
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 4);
}
{
flat_multimap<std::string, int, std::less<>> s0{{"hello", 42}, {"world", 84}};
REQUIRE(s0.find(std::string_view("hello")) == s0.begin());
REQUIRE(my_as_const(s0).find(std::string_view("world")) == s0.begin() + 1);
REQUIRE(s0.find(std::string_view("42")) == s0.end());
REQUIRE(my_as_const(s0).find(std::string_view("42")) == s0.cend());
}
}
SECTION("heterogeneous") {
flat_multimap<std::string, int, std::less<>> s0{{"hello", 42}, {"world", 84}};
REQUIRE(s0.find(std::string_view("hello")) == s0.begin());
REQUIRE(my_as_const(s0).find(std::string_view("world")) == s0.begin() + 1);
REQUIRE(s0.find(std::string_view("42")) == s0.end());
REQUIRE(my_as_const(s0).find(std::string_view("42")) == s0.cend());
REQUIRE(my_as_const(s0).count(std::string_view("hello")) == 1);
REQUIRE(my_as_const(s0).count(std::string_view("hello_42")) == 0);
REQUIRE(s0.upper_bound(std::string_view("hello")) == s0.begin() + 1);
REQUIRE(my_as_const(s0).upper_bound(std::string_view("hello")) == s0.begin() + 1);
REQUIRE(s0.erase(std::string_view("hello")) == 1);
REQUIRE(s0.at(std::string_view("world")) == 84);
REQUIRE(my_as_const(s0).at(std::string_view("world")) == 84);
}
SECTION("observers") {
struct my_less {

View File

@@ -388,13 +388,21 @@ TEST_CASE("flat_multiset") {
REQUIRE(my_as_const(s0).lower_bound(-1) == s0.cbegin());
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 4);
}
{
flat_multiset<std::string, std::less<>> s0{"hello", "world"};
REQUIRE(s0.find(std::string_view("hello")) == s0.begin());
REQUIRE(my_as_const(s0).find(std::string_view("world")) == s0.begin() + 1);
REQUIRE(s0.find(std::string_view("42")) == s0.end());
REQUIRE(my_as_const(s0).find(std::string_view("42")) == s0.cend());
}
}
SECTION("heterogeneous") {
flat_multiset<std::string, std::less<>> s0{"hello", "world"};
REQUIRE(s0.find(std::string_view("hello")) == s0.begin());
REQUIRE(my_as_const(s0).find(std::string_view("world")) == s0.begin() + 1);
REQUIRE(s0.find(std::string_view("42")) == s0.end());
REQUIRE(my_as_const(s0).find(std::string_view("42")) == s0.cend());
REQUIRE(my_as_const(s0).count(std::string_view("hello")) == 1);
REQUIRE(my_as_const(s0).count(std::string_view("hello_42")) == 0);
REQUIRE(s0.upper_bound(std::string_view("hello")) == s0.begin() + 1);
REQUIRE(my_as_const(s0).upper_bound(std::string_view("hello")) == s0.begin() + 1);
REQUIRE(s0.erase(std::string_view("hello")) == 1);
}
SECTION("observers") {
struct my_less {

View File

@@ -386,13 +386,21 @@ TEST_CASE("flat_set") {
REQUIRE(my_as_const(s0).lower_bound(-1) == s0.cbegin());
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 3);
}
{
flat_set<std::string, std::less<>> s0{"hello", "world"};
REQUIRE(s0.find(std::string_view("hello")) == s0.begin());
REQUIRE(my_as_const(s0).find(std::string_view("world")) == s0.begin() + 1);
REQUIRE(s0.find(std::string_view("42")) == s0.end());
REQUIRE(my_as_const(s0).find(std::string_view("42")) == s0.cend());
}
}
SECTION("heterogeneous") {
flat_set<std::string, std::less<>> s0{"hello", "world"};
REQUIRE(s0.find(std::string_view("hello")) == s0.begin());
REQUIRE(my_as_const(s0).find(std::string_view("world")) == s0.begin() + 1);
REQUIRE(s0.find(std::string_view("42")) == s0.end());
REQUIRE(my_as_const(s0).find(std::string_view("42")) == s0.cend());
REQUIRE(my_as_const(s0).count(std::string_view("hello")) == 1);
REQUIRE(my_as_const(s0).count(std::string_view("hello_42")) == 0);
REQUIRE(s0.upper_bound(std::string_view("hello")) == s0.begin() + 1);
REQUIRE(my_as_const(s0).upper_bound(std::string_view("hello")) == s0.begin() + 1);
REQUIRE(s0.erase(std::string_view("hello")) == 1);
}
SECTION("observers") {
struct my_less {