mirror of
https://github.com/BlackMATov/flat.hpp.git
synced 2025-12-13 09:45:38 +07:00
@@ -1,7 +1,6 @@
|
|||||||
version: "{build}"
|
version: "{build}"
|
||||||
shallow_clone: true
|
shallow_clone: true
|
||||||
image:
|
image:
|
||||||
- Visual Studio 2015
|
|
||||||
- Visual Studio 2017
|
- Visual Studio 2017
|
||||||
- Visual Studio 2019 Preview
|
- Visual Studio 2019 Preview
|
||||||
platform:
|
platform:
|
||||||
|
|||||||
@@ -9,14 +9,6 @@ matrix:
|
|||||||
dist: trusty
|
dist: trusty
|
||||||
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-8"] } }
|
addons: { apt: { sources: ubuntu-toolchain-r-test, packages: ["xorg-dev", "g++-8"] } }
|
||||||
env: MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
|
env: MATRIX_EVAL="CC=gcc-8 && CXX=g++-8"
|
||||||
- os: linux
|
|
||||||
dist: trusty
|
|
||||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-5.0"], packages: ["xorg-dev", "clang-5.0", "g++-7"] } }
|
|
||||||
env: MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0"
|
|
||||||
- os: linux
|
|
||||||
dist: trusty
|
|
||||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-6.0"], packages: ["xorg-dev", "clang-6.0", "g++-7"] } }
|
|
||||||
env: MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0"
|
|
||||||
- os: linux
|
- os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-7"], packages: ["xorg-dev", "clang-7", "g++-7"] } }
|
addons: { apt: { sources: ["ubuntu-toolchain-r-test", "llvm-toolchain-trusty-7"], packages: ["xorg-dev", "clang-7", "g++-7"] } }
|
||||||
@@ -35,7 +27,6 @@ before_install:
|
|||||||
- if [ "$TRAVIS_OS_NAME" == 'osx' ]; then
|
- if [ "$TRAVIS_OS_NAME" == 'osx' ]; then
|
||||||
brew update;
|
brew update;
|
||||||
brew upgrade cmake;
|
brew upgrade cmake;
|
||||||
brew install git-lfs;
|
|
||||||
fi
|
fi
|
||||||
- if [ "$TRAVIS_OS_NAME" == 'linux' ]; then
|
- if [ "$TRAVIS_OS_NAME" == 'linux' ]; then
|
||||||
mkdir $HOME/cmake;
|
mkdir $HOME/cmake;
|
||||||
|
|||||||
62
README.md
62
README.md
@@ -183,6 +183,7 @@ void clear();
|
|||||||
iterator erase(const_iterator iter);
|
iterator erase(const_iterator iter);
|
||||||
iterator erase(const_iterator first, const_iterator last);
|
iterator erase(const_iterator first, const_iterator last);
|
||||||
size_type erase(const key_type& key);
|
size_type erase(const key_type& key);
|
||||||
|
template < typename K > size_type erase(const K& key);
|
||||||
|
|
||||||
void swap(flat_set& other);
|
void swap(flat_set& other);
|
||||||
```
|
```
|
||||||
@@ -191,18 +192,31 @@ void swap(flat_set& other);
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
size_type count(const key_type& key) const;
|
size_type count(const key_type& key) const;
|
||||||
|
template < typename K > size_type count(const K& key) const;
|
||||||
|
|
||||||
iterator find(const key_type& key);
|
iterator find(const key_type& key);
|
||||||
const_iterator find(const key_type& key) const;
|
const_iterator find(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator find(const K& key);
|
||||||
|
template < typename K > const_iterator find(const K& key) const;
|
||||||
|
|
||||||
std::pair<iterator, iterator> equal_range(const key_type& key);
|
std::pair<iterator, iterator> equal_range(const key_type& key);
|
||||||
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
|
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > std::pair<iterator, iterator> equal_range(const K& key);
|
||||||
|
template < typename K > std::pair<const_iterator, const_iterator> equal_range(const K& key) const;
|
||||||
|
|
||||||
iterator lower_bound(const key_type& key);
|
iterator lower_bound(const key_type& key);
|
||||||
const_iterator lower_bound(const key_type& key) const;
|
const_iterator lower_bound(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator lower_bound(const K& key);
|
||||||
|
template < typename K > const_iterator lower_bound(const K& key) const;
|
||||||
|
|
||||||
iterator upper_bound(const key_type& key);
|
iterator upper_bound(const key_type& key);
|
||||||
const_iterator upper_bound(const key_type& key) const;
|
const_iterator upper_bound(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator upper_bound(const K& key);
|
||||||
|
template < typename K > const_iterator upper_bound(const K& key) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Observers
|
### Observers
|
||||||
@@ -390,6 +404,9 @@ mapped_type& operator[](const key_type& key);
|
|||||||
|
|
||||||
mapped_type& at(const key_type& key);
|
mapped_type& at(const key_type& key);
|
||||||
const mapped_type& at(const key_type& key) const;
|
const mapped_type& at(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > mapped_type& at(const K& key);
|
||||||
|
template < typename K > const mapped_type& at(const K& key) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Modifiers
|
### Modifiers
|
||||||
@@ -414,6 +431,7 @@ void clear();
|
|||||||
iterator erase(const_iterator iter);
|
iterator erase(const_iterator iter);
|
||||||
iterator erase(const_iterator first, const_iterator last);
|
iterator erase(const_iterator first, const_iterator last);
|
||||||
size_type erase(const key_type& key);
|
size_type erase(const key_type& key);
|
||||||
|
template < typename K > size_type erase(const K& key);
|
||||||
|
|
||||||
void swap(flat_map& other)
|
void swap(flat_map& other)
|
||||||
```
|
```
|
||||||
@@ -422,18 +440,31 @@ void swap(flat_map& other)
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
size_type count(const key_type& key) const;
|
size_type count(const key_type& key) const;
|
||||||
|
template < typename K > size_type count(const K& key) const;
|
||||||
|
|
||||||
iterator find(const key_type& key);
|
iterator find(const key_type& key);
|
||||||
const_iterator find(const key_type& key) const;
|
const_iterator find(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator find(const K& key);
|
||||||
|
template < typename K > const_iterator find(const K& key) const;
|
||||||
|
|
||||||
std::pair<iterator, iterator> equal_range(const key_type& key);
|
std::pair<iterator, iterator> equal_range(const key_type& key);
|
||||||
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
|
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > std::pair<iterator, iterator> equal_range(const K& key);
|
||||||
|
template < typename K > std::pair<const_iterator, const_iterator> equal_range(const K& key) const;
|
||||||
|
|
||||||
iterator lower_bound(const key_type& key);
|
iterator lower_bound(const key_type& key);
|
||||||
const_iterator lower_bound(const key_type& key) const;
|
const_iterator lower_bound(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator lower_bound(const K& key);
|
||||||
|
template < typename K > const_iterator lower_bound(const K& key) const;
|
||||||
|
|
||||||
iterator upper_bound(const key_type& key);
|
iterator upper_bound(const key_type& key);
|
||||||
const_iterator upper_bound(const key_type& key) const;
|
const_iterator upper_bound(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator upper_bound(const K& key);
|
||||||
|
template < typename K > const_iterator upper_bound(const K& key) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Observers
|
### Observers
|
||||||
@@ -635,6 +666,7 @@ void clear();
|
|||||||
iterator erase(const_iterator iter);
|
iterator erase(const_iterator iter);
|
||||||
iterator erase(const_iterator first, const_iterator last);
|
iterator erase(const_iterator first, const_iterator last);
|
||||||
size_type erase(const key_type& key);
|
size_type erase(const key_type& key);
|
||||||
|
template < typename K > size_type erase(const K& key);
|
||||||
|
|
||||||
void swap(flat_multiset& other);
|
void swap(flat_multiset& other);
|
||||||
```
|
```
|
||||||
@@ -643,18 +675,31 @@ void swap(flat_multiset& other);
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
size_type count(const key_type& key) const;
|
size_type count(const key_type& key) const;
|
||||||
|
template < typename K > size_type count(const K& key) const;
|
||||||
|
|
||||||
iterator find(const key_type& key);
|
iterator find(const key_type& key);
|
||||||
const_iterator find(const key_type& key) const;
|
const_iterator find(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator find(const K& key);
|
||||||
|
template < typename K > const_iterator find(const K& key) const;
|
||||||
|
|
||||||
std::pair<iterator, iterator> equal_range(const key_type& key);
|
std::pair<iterator, iterator> equal_range(const key_type& key);
|
||||||
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
|
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > std::pair<iterator, iterator> equal_range(const K& key);
|
||||||
|
template < typename K > std::pair<const_iterator, const_iterator> equal_range(const K& key) const;
|
||||||
|
|
||||||
iterator lower_bound(const key_type& key);
|
iterator lower_bound(const key_type& key);
|
||||||
const_iterator lower_bound(const key_type& key) const;
|
const_iterator lower_bound(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator lower_bound(const K& key);
|
||||||
|
template < typename K > const_iterator lower_bound(const K& key) const;
|
||||||
|
|
||||||
iterator upper_bound(const key_type& key);
|
iterator upper_bound(const key_type& key);
|
||||||
const_iterator upper_bound(const key_type& key) const;
|
const_iterator upper_bound(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator upper_bound(const K& key);
|
||||||
|
template < typename K > const_iterator upper_bound(const K& key) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Observers
|
### Observers
|
||||||
@@ -842,6 +887,9 @@ mapped_type& operator[](const key_type& key);
|
|||||||
|
|
||||||
mapped_type& at(const key_type& key);
|
mapped_type& at(const key_type& key);
|
||||||
const mapped_type& at(const key_type& key) const;
|
const mapped_type& at(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > mapped_type& at(const K& key);
|
||||||
|
template < typename K > const mapped_type& at(const K& key) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Modifiers
|
### Modifiers
|
||||||
@@ -866,6 +914,7 @@ void clear();
|
|||||||
iterator erase(const_iterator iter);
|
iterator erase(const_iterator iter);
|
||||||
iterator erase(const_iterator first, const_iterator last);
|
iterator erase(const_iterator first, const_iterator last);
|
||||||
size_type erase(const key_type& key);
|
size_type erase(const key_type& key);
|
||||||
|
template < typename K > size_type erase(const K& key);
|
||||||
|
|
||||||
void swap(flat_multimap& other)
|
void swap(flat_multimap& other)
|
||||||
```
|
```
|
||||||
@@ -874,18 +923,31 @@ void swap(flat_multimap& other)
|
|||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
size_type count(const key_type& key) const;
|
size_type count(const key_type& key) const;
|
||||||
|
template < typename K > size_type count(const K& key) const;
|
||||||
|
|
||||||
iterator find(const key_type& key);
|
iterator find(const key_type& key);
|
||||||
const_iterator find(const key_type& key) const;
|
const_iterator find(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator find(const K& key);
|
||||||
|
template < typename K > const_iterator find(const K& key) const;
|
||||||
|
|
||||||
std::pair<iterator, iterator> equal_range(const key_type& key);
|
std::pair<iterator, iterator> equal_range(const key_type& key);
|
||||||
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
|
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > std::pair<iterator, iterator> equal_range(const K& key);
|
||||||
|
template < typename K > std::pair<const_iterator, const_iterator> equal_range(const K& key) const;
|
||||||
|
|
||||||
iterator lower_bound(const key_type& key);
|
iterator lower_bound(const key_type& key);
|
||||||
const_iterator lower_bound(const key_type& key) const;
|
const_iterator lower_bound(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator lower_bound(const K& key);
|
||||||
|
template < typename K > const_iterator lower_bound(const K& key) const;
|
||||||
|
|
||||||
iterator upper_bound(const key_type& key);
|
iterator upper_bound(const key_type& key);
|
||||||
const_iterator upper_bound(const key_type& key) const;
|
const_iterator upper_bound(const key_type& key) const;
|
||||||
|
|
||||||
|
template < typename K > iterator upper_bound(const K& key);
|
||||||
|
template < typename K > const_iterator upper_bound(const K& key) const;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Observers
|
### Observers
|
||||||
|
|||||||
23
headers/flat.hpp/detail/is_transparent.hpp
Normal file
23
headers/flat.hpp/detail/is_transparent.hpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/flat.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace flat_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename T, typename U, typename = void >
|
||||||
|
struct is_transparent
|
||||||
|
: std::false_type {};
|
||||||
|
|
||||||
|
template < typename T, typename U >
|
||||||
|
struct is_transparent<T, U, std::void_t<typename T::is_transparent>>
|
||||||
|
: std::true_type {};
|
||||||
|
|
||||||
|
template < typename T, typename U >
|
||||||
|
inline constexpr bool is_transparent_v = is_transparent<T, U>::value;
|
||||||
|
}
|
||||||
62
headers/flat.hpp/detail/pair_compare.hpp
Normal file
62
headers/flat.hpp/detail/pair_compare.hpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "https://github.com/blackmatov/flat.hpp"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com)
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "is_transparent.hpp"
|
||||||
|
|
||||||
|
namespace flat_hpp::detail
|
||||||
|
{
|
||||||
|
template < typename Pair, typename Compare >
|
||||||
|
class pair_compare : public Compare {
|
||||||
|
public:
|
||||||
|
pair_compare() = default;
|
||||||
|
|
||||||
|
pair_compare(const Compare& compare)
|
||||||
|
: Compare(compare) {}
|
||||||
|
|
||||||
|
bool operator()(
|
||||||
|
const typename Pair::first_type& l,
|
||||||
|
const typename Pair::first_type& r) const
|
||||||
|
{
|
||||||
|
return Compare::operator()(l, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(const Pair& l, const Pair& r) const {
|
||||||
|
return Compare::operator()(l.first, r.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(
|
||||||
|
const typename Pair::first_type& l,
|
||||||
|
const Pair& r) const
|
||||||
|
{
|
||||||
|
return Compare::operator()(l, r.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(
|
||||||
|
const Pair& l,
|
||||||
|
const typename Pair::first_type& r) const
|
||||||
|
{
|
||||||
|
return Compare::operator()(l.first, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
is_transparent_v<Compare, K>,
|
||||||
|
bool>
|
||||||
|
operator()(const K& l, const Pair& r) const {
|
||||||
|
return Compare::operator()(l, r.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
is_transparent_v<Compare, K>,
|
||||||
|
bool>
|
||||||
|
operator()(const Pair& l, const K& r) const {
|
||||||
|
return Compare::operator()(l.first, r);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -15,55 +15,21 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
|
||||||
|
#include "detail/pair_compare.hpp"
|
||||||
|
#include "detail/is_transparent.hpp"
|
||||||
|
|
||||||
namespace flat_hpp
|
namespace flat_hpp
|
||||||
{
|
{
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template < typename Value, typename Compare >
|
|
||||||
class flat_map_compare : public Compare {
|
|
||||||
public:
|
|
||||||
flat_map_compare() = default;
|
|
||||||
|
|
||||||
flat_map_compare(const Compare& compare)
|
|
||||||
: Compare(compare) {}
|
|
||||||
|
|
||||||
bool operator()(
|
|
||||||
const typename Value::first_type& l,
|
|
||||||
const typename Value::first_type& r) const
|
|
||||||
{
|
|
||||||
return Compare::operator()(l, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(
|
|
||||||
const typename Value::first_type& l,
|
|
||||||
const Value& r) const
|
|
||||||
{
|
|
||||||
return Compare::operator()(l, r.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(
|
|
||||||
const Value& l,
|
|
||||||
const typename Value::first_type& r) const
|
|
||||||
{
|
|
||||||
return Compare::operator()(l.first, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const Value& l, const Value& r) const {
|
|
||||||
return Compare::operator()(l.first, r.first);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Key
|
template < typename Key
|
||||||
, typename Value
|
, typename Value
|
||||||
, typename Compare = std::less<Key>
|
, typename Compare = std::less<Key>
|
||||||
, typename Container = std::vector<std::pair<Key, Value>> >
|
, typename Container = std::vector<std::pair<Key, Value>> >
|
||||||
class flat_map
|
class flat_map
|
||||||
: private detail::flat_map_compare<
|
: private detail::pair_compare<
|
||||||
typename Container::value_type,
|
typename Container::value_type,
|
||||||
Compare>
|
Compare>
|
||||||
{
|
{
|
||||||
using base_type = detail::flat_map_compare<
|
using base_type = detail::pair_compare<
|
||||||
typename Container::value_type,
|
typename Container::value_type,
|
||||||
Compare>;
|
Compare>;
|
||||||
public:
|
public:
|
||||||
@@ -299,6 +265,30 @@ namespace flat_hpp
|
|||||||
throw std::out_of_range("flat_map::at: key not found");
|
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) {
|
std::pair<iterator, bool> insert(value_type&& value) {
|
||||||
const iterator iter = lower_bound(value.first);
|
const iterator iter = lower_bound(value.first);
|
||||||
return iter == end() || this->operator()(value, *iter)
|
return iter == end() || this->operator()(value, *iter)
|
||||||
@@ -362,7 +352,18 @@ namespace flat_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_type erase(const key_type& key) {
|
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()
|
return iter != end()
|
||||||
? (erase(iter), 1)
|
? (erase(iter), 1)
|
||||||
: 0;
|
: 0;
|
||||||
@@ -384,16 +385,47 @@ namespace flat_hpp
|
|||||||
return iter != end() ? 1 : 0;
|
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) {
|
iterator find(const key_type& key) {
|
||||||
const iterator iter = lower_bound(key);
|
const iterator iter = lower_bound(key);
|
||||||
return iter != end() && !this->operator()(key, iter->first)
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
? iter
|
? iter
|
||||||
: end();
|
: end();
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator find(const key_type& key) const {
|
const_iterator find(const key_type& key) const {
|
||||||
const const_iterator iter = lower_bound(key);
|
const const_iterator iter = lower_bound(key);
|
||||||
return iter != end() && !this->operator()(key, iter->first)
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
|
? iter
|
||||||
|
: end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
find(const K& key) {
|
||||||
|
const iterator iter = lower_bound(key);
|
||||||
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
|
? iter
|
||||||
|
: end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
find(const K& key) const {
|
||||||
|
const const_iterator iter = lower_bound(key);
|
||||||
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
? iter
|
? iter
|
||||||
: end();
|
: end();
|
||||||
}
|
}
|
||||||
@@ -408,6 +440,24 @@ namespace flat_hpp
|
|||||||
return std::equal_range(begin(), end(), key, comp);
|
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) {
|
iterator lower_bound(const key_type& key) {
|
||||||
const base_type& comp = *this;
|
const base_type& comp = *this;
|
||||||
return std::lower_bound(begin(), end(), key, comp);
|
return std::lower_bound(begin(), end(), key, comp);
|
||||||
@@ -418,6 +468,24 @@ namespace flat_hpp
|
|||||||
return std::lower_bound(begin(), end(), key, comp);
|
return std::lower_bound(begin(), end(), key, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
lower_bound(const K& key) {
|
||||||
|
const base_type& comp = *this;
|
||||||
|
return std::lower_bound(begin(), end(), key, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
lower_bound(const K& key) const {
|
||||||
|
const base_type& comp = *this;
|
||||||
|
return std::lower_bound(begin(), end(), key, comp);
|
||||||
|
}
|
||||||
|
|
||||||
iterator upper_bound(const key_type& key) {
|
iterator upper_bound(const key_type& key) {
|
||||||
const base_type& comp = *this;
|
const base_type& comp = *this;
|
||||||
return std::upper_bound(begin(), end(), key, comp);
|
return std::upper_bound(begin(), end(), key, comp);
|
||||||
@@ -428,6 +496,24 @@ namespace flat_hpp
|
|||||||
return std::upper_bound(begin(), end(), key, comp);
|
return std::upper_bound(begin(), end(), key, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
upper_bound(const K& key) {
|
||||||
|
const base_type& comp = *this;
|
||||||
|
return std::upper_bound(begin(), end(), key, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
upper_bound(const K& key) const {
|
||||||
|
const base_type& comp = *this;
|
||||||
|
return std::upper_bound(begin(), end(), key, comp);
|
||||||
|
}
|
||||||
|
|
||||||
key_compare key_comp() const {
|
key_compare key_comp() const {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,55 +15,21 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
|
||||||
|
#include "detail/pair_compare.hpp"
|
||||||
|
#include "detail/is_transparent.hpp"
|
||||||
|
|
||||||
namespace flat_hpp
|
namespace flat_hpp
|
||||||
{
|
{
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template < typename Value, typename Compare >
|
|
||||||
class flat_multimap_compare : public Compare {
|
|
||||||
public:
|
|
||||||
flat_multimap_compare() = default;
|
|
||||||
|
|
||||||
flat_multimap_compare(const Compare& compare)
|
|
||||||
: Compare(compare) {}
|
|
||||||
|
|
||||||
bool operator()(
|
|
||||||
const typename Value::first_type& l,
|
|
||||||
const typename Value::first_type& r) const
|
|
||||||
{
|
|
||||||
return Compare::operator()(l, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(
|
|
||||||
const typename Value::first_type& l,
|
|
||||||
const Value& r) const
|
|
||||||
{
|
|
||||||
return Compare::operator()(l, r.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(
|
|
||||||
const Value& l,
|
|
||||||
const typename Value::first_type& r) const
|
|
||||||
{
|
|
||||||
return Compare::operator()(l.first, r);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator()(const Value& l, const Value& r) const {
|
|
||||||
return Compare::operator()(l.first, r.first);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template < typename Key
|
template < typename Key
|
||||||
, typename Value
|
, typename Value
|
||||||
, typename Compare = std::less<Key>
|
, typename Compare = std::less<Key>
|
||||||
, typename Container = std::vector<std::pair<Key, Value>> >
|
, typename Container = std::vector<std::pair<Key, Value>> >
|
||||||
class flat_multimap
|
class flat_multimap
|
||||||
: private detail::flat_multimap_compare<
|
: private detail::pair_compare<
|
||||||
typename Container::value_type,
|
typename Container::value_type,
|
||||||
Compare>
|
Compare>
|
||||||
{
|
{
|
||||||
using base_type = detail::flat_multimap_compare<
|
using base_type = detail::pair_compare<
|
||||||
typename Container::value_type,
|
typename Container::value_type,
|
||||||
Compare>;
|
Compare>;
|
||||||
public:
|
public:
|
||||||
@@ -299,6 +265,30 @@ namespace flat_hpp
|
|||||||
throw std::out_of_range("flat_multimap::at: key not found");
|
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) {
|
iterator insert(value_type&& value) {
|
||||||
const iterator iter = upper_bound(value.first);
|
const iterator iter = upper_bound(value.first);
|
||||||
return data_.insert(iter, std::move(value));
|
return data_.insert(iter, std::move(value));
|
||||||
@@ -364,6 +354,17 @@ namespace flat_hpp
|
|||||||
return r;
|
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)
|
void swap(flat_multimap& other)
|
||||||
noexcept(std::is_nothrow_swappable_v<base_type>
|
noexcept(std::is_nothrow_swappable_v<base_type>
|
||||||
&& std::is_nothrow_swappable_v<container_type>)
|
&& std::is_nothrow_swappable_v<container_type>)
|
||||||
@@ -380,16 +381,47 @@ namespace flat_hpp
|
|||||||
return std::distance(p.first, p.second);
|
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) {
|
iterator find(const key_type& key) {
|
||||||
const iterator iter = lower_bound(key);
|
const iterator iter = lower_bound(key);
|
||||||
return iter != end() && !this->operator()(key, iter->first)
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
? iter
|
? iter
|
||||||
: end();
|
: end();
|
||||||
}
|
}
|
||||||
|
|
||||||
const_iterator find(const key_type& key) const {
|
const_iterator find(const key_type& key) const {
|
||||||
const const_iterator iter = lower_bound(key);
|
const const_iterator iter = lower_bound(key);
|
||||||
return iter != end() && !this->operator()(key, iter->first)
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
|
? iter
|
||||||
|
: end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
find(const K& key) {
|
||||||
|
const iterator iter = lower_bound(key);
|
||||||
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
|
? iter
|
||||||
|
: end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
find(const K& key) const {
|
||||||
|
const const_iterator iter = lower_bound(key);
|
||||||
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
? iter
|
? iter
|
||||||
: end();
|
: end();
|
||||||
}
|
}
|
||||||
@@ -404,6 +436,24 @@ namespace flat_hpp
|
|||||||
return std::equal_range(begin(), end(), key, comp);
|
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) {
|
iterator lower_bound(const key_type& key) {
|
||||||
const base_type& comp = *this;
|
const base_type& comp = *this;
|
||||||
return std::lower_bound(begin(), end(), key, comp);
|
return std::lower_bound(begin(), end(), key, comp);
|
||||||
@@ -414,6 +464,24 @@ namespace flat_hpp
|
|||||||
return std::lower_bound(begin(), end(), key, comp);
|
return std::lower_bound(begin(), end(), key, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
lower_bound(const K& key) {
|
||||||
|
const base_type& comp = *this;
|
||||||
|
return std::lower_bound(begin(), end(), key, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
lower_bound(const K& key) const {
|
||||||
|
const base_type& comp = *this;
|
||||||
|
return std::lower_bound(begin(), end(), key, comp);
|
||||||
|
}
|
||||||
|
|
||||||
iterator upper_bound(const key_type& key) {
|
iterator upper_bound(const key_type& key) {
|
||||||
const base_type& comp = *this;
|
const base_type& comp = *this;
|
||||||
return std::upper_bound(begin(), end(), key, comp);
|
return std::upper_bound(begin(), end(), key, comp);
|
||||||
@@ -424,6 +492,24 @@ namespace flat_hpp
|
|||||||
return std::upper_bound(begin(), end(), key, comp);
|
return std::upper_bound(begin(), end(), key, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
upper_bound(const K& key) {
|
||||||
|
const base_type& comp = *this;
|
||||||
|
return std::upper_bound(begin(), end(), key, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
upper_bound(const K& key) const {
|
||||||
|
const base_type& comp = *this;
|
||||||
|
return std::upper_bound(begin(), end(), key, comp);
|
||||||
|
}
|
||||||
|
|
||||||
key_compare key_comp() const {
|
key_compare key_comp() const {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
|
||||||
|
#include "detail/is_transparent.hpp"
|
||||||
|
|
||||||
namespace flat_hpp
|
namespace flat_hpp
|
||||||
{
|
{
|
||||||
template < typename Key
|
template < typename Key
|
||||||
@@ -279,6 +281,17 @@ namespace flat_hpp
|
|||||||
return r;
|
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)
|
void swap(flat_multiset& other)
|
||||||
noexcept(std::is_nothrow_swappable_v<base_type>
|
noexcept(std::is_nothrow_swappable_v<base_type>
|
||||||
&& std::is_nothrow_swappable_v<container_type>)
|
&& std::is_nothrow_swappable_v<container_type>)
|
||||||
@@ -295,6 +308,15 @@ namespace flat_hpp
|
|||||||
return std::distance(p.first, p.second);
|
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) {
|
iterator find(const key_type& key) {
|
||||||
const iterator iter = lower_bound(key);
|
const iterator iter = lower_bound(key);
|
||||||
return iter != end() && !this->operator()(key, *iter)
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
@@ -309,6 +331,28 @@ namespace flat_hpp
|
|||||||
: end();
|
: end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
find(const K& key) {
|
||||||
|
const iterator iter = lower_bound(key);
|
||||||
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
|
? iter
|
||||||
|
: end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
find(const K& key) const {
|
||||||
|
const const_iterator iter = lower_bound(key);
|
||||||
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
|
? iter
|
||||||
|
: end();
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<iterator, iterator> equal_range(const key_type& key) {
|
std::pair<iterator, iterator> equal_range(const key_type& key) {
|
||||||
return std::equal_range(begin(), end(), key, key_comp());
|
return std::equal_range(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
@@ -317,6 +361,22 @@ namespace flat_hpp
|
|||||||
return std::equal_range(begin(), end(), key, key_comp());
|
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) {
|
iterator lower_bound(const key_type& key) {
|
||||||
return std::lower_bound(begin(), end(), key, key_comp());
|
return std::lower_bound(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
@@ -325,6 +385,22 @@ namespace flat_hpp
|
|||||||
return std::lower_bound(begin(), end(), key, key_comp());
|
return std::lower_bound(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
lower_bound(const K& key) {
|
||||||
|
return std::lower_bound(begin(), end(), key, key_comp());
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
lower_bound(const K& key) const {
|
||||||
|
return std::lower_bound(begin(), end(), key, key_comp());
|
||||||
|
}
|
||||||
|
|
||||||
iterator upper_bound(const key_type& key) {
|
iterator upper_bound(const key_type& key) {
|
||||||
return std::upper_bound(begin(), end(), key, key_comp());
|
return std::upper_bound(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
@@ -333,6 +409,22 @@ namespace flat_hpp
|
|||||||
return std::upper_bound(begin(), end(), key, key_comp());
|
return std::upper_bound(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
upper_bound(const K& key) {
|
||||||
|
return std::upper_bound(begin(), end(), key, key_comp());
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
upper_bound(const K& key) const {
|
||||||
|
return std::upper_bound(begin(), end(), key, key_comp());
|
||||||
|
}
|
||||||
|
|
||||||
key_compare key_comp() const {
|
key_compare key_comp() const {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <initializer_list>
|
#include <initializer_list>
|
||||||
|
|
||||||
|
#include "detail/is_transparent.hpp"
|
||||||
|
|
||||||
namespace flat_hpp
|
namespace flat_hpp
|
||||||
{
|
{
|
||||||
template < typename Key
|
template < typename Key
|
||||||
@@ -277,7 +279,18 @@ namespace flat_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_type erase(const key_type& key) {
|
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()
|
return iter != end()
|
||||||
? (erase(iter), 1)
|
? (erase(iter), 1)
|
||||||
: 0;
|
: 0;
|
||||||
@@ -299,6 +312,15 @@ namespace flat_hpp
|
|||||||
return iter != end() ? 1 : 0;
|
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) {
|
iterator find(const key_type& key) {
|
||||||
const iterator iter = lower_bound(key);
|
const iterator iter = lower_bound(key);
|
||||||
return iter != end() && !this->operator()(key, *iter)
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
@@ -313,6 +335,28 @@ namespace flat_hpp
|
|||||||
: end();
|
: end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
find(const K& key) {
|
||||||
|
const iterator iter = lower_bound(key);
|
||||||
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
|
? iter
|
||||||
|
: end();
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
find(const K& key) const {
|
||||||
|
const const_iterator iter = lower_bound(key);
|
||||||
|
return iter != end() && !this->operator()(key, *iter)
|
||||||
|
? iter
|
||||||
|
: end();
|
||||||
|
}
|
||||||
|
|
||||||
std::pair<iterator, iterator> equal_range(const key_type& key) {
|
std::pair<iterator, iterator> equal_range(const key_type& key) {
|
||||||
return std::equal_range(begin(), end(), key, key_comp());
|
return std::equal_range(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
@@ -321,6 +365,22 @@ namespace flat_hpp
|
|||||||
return std::equal_range(begin(), end(), key, key_comp());
|
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) {
|
iterator lower_bound(const key_type& key) {
|
||||||
return std::lower_bound(begin(), end(), key, key_comp());
|
return std::lower_bound(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
@@ -329,6 +389,22 @@ namespace flat_hpp
|
|||||||
return std::lower_bound(begin(), end(), key, key_comp());
|
return std::lower_bound(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
lower_bound(const K& key) {
|
||||||
|
return std::lower_bound(begin(), end(), key, key_comp());
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
lower_bound(const K& key) const {
|
||||||
|
return std::lower_bound(begin(), end(), key, key_comp());
|
||||||
|
}
|
||||||
|
|
||||||
iterator upper_bound(const key_type& key) {
|
iterator upper_bound(const key_type& key) {
|
||||||
return std::upper_bound(begin(), end(), key, key_comp());
|
return std::upper_bound(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
@@ -337,6 +413,22 @@ namespace flat_hpp
|
|||||||
return std::upper_bound(begin(), end(), key, key_comp());
|
return std::upper_bound(begin(), end(), key, key_comp());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
iterator>
|
||||||
|
upper_bound(const K& key) {
|
||||||
|
return std::upper_bound(begin(), end(), key, key_comp());
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename K >
|
||||||
|
std::enable_if_t<
|
||||||
|
detail::is_transparent_v<Compare, K>,
|
||||||
|
const_iterator>
|
||||||
|
upper_bound(const K& key) const {
|
||||||
|
return std::upper_bound(begin(), end(), key, key_comp());
|
||||||
|
}
|
||||||
|
|
||||||
key_compare key_comp() const {
|
key_compare key_comp() const {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include <flat.hpp/flat_map.hpp>
|
#include <flat.hpp/flat_map.hpp>
|
||||||
using namespace flat_hpp;
|
using namespace flat_hpp;
|
||||||
|
|
||||||
@@ -54,6 +57,10 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("flat_map") {
|
TEST_CASE("flat_map") {
|
||||||
|
SECTION("detail") {
|
||||||
|
STATIC_REQUIRE(detail::is_transparent<std::less<>, int>::value);
|
||||||
|
STATIC_REQUIRE_FALSE(detail::is_transparent<std::less<int>, int>::value);
|
||||||
|
}
|
||||||
SECTION("sizeof") {
|
SECTION("sizeof") {
|
||||||
REQUIRE(sizeof(flat_map<int, unsigned>) == sizeof(std::vector<std::pair<int, unsigned>>));
|
REQUIRE(sizeof(flat_map<int, unsigned>) == sizeof(std::vector<std::pair<int, unsigned>>));
|
||||||
|
|
||||||
@@ -404,6 +411,23 @@ TEST_CASE("flat_map") {
|
|||||||
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 3);
|
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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") {
|
SECTION("observers") {
|
||||||
struct my_less {
|
struct my_less {
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include <flat.hpp/flat_multimap.hpp>
|
#include <flat.hpp/flat_multimap.hpp>
|
||||||
using namespace flat_hpp;
|
using namespace flat_hpp;
|
||||||
|
|
||||||
@@ -54,6 +57,10 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("flat_multimap") {
|
TEST_CASE("flat_multimap") {
|
||||||
|
SECTION("detail") {
|
||||||
|
STATIC_REQUIRE(detail::is_transparent<std::less<>, int>::value);
|
||||||
|
STATIC_REQUIRE_FALSE(detail::is_transparent<std::less<int>, int>::value);
|
||||||
|
}
|
||||||
SECTION("sizeof") {
|
SECTION("sizeof") {
|
||||||
REQUIRE(sizeof(flat_multimap<int, unsigned>) == sizeof(std::vector<std::pair<int, unsigned>>));
|
REQUIRE(sizeof(flat_multimap<int, unsigned>) == sizeof(std::vector<std::pair<int, unsigned>>));
|
||||||
|
|
||||||
@@ -406,6 +413,23 @@ TEST_CASE("flat_multimap") {
|
|||||||
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 4);
|
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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") {
|
SECTION("observers") {
|
||||||
struct my_less {
|
struct my_less {
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include <flat.hpp/flat_multiset.hpp>
|
#include <flat.hpp/flat_multiset.hpp>
|
||||||
using namespace flat_hpp;
|
using namespace flat_hpp;
|
||||||
|
|
||||||
@@ -54,6 +57,10 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("flat_multiset") {
|
TEST_CASE("flat_multiset") {
|
||||||
|
SECTION("detail") {
|
||||||
|
STATIC_REQUIRE(detail::is_transparent<std::less<>, int>::value);
|
||||||
|
STATIC_REQUIRE_FALSE(detail::is_transparent<std::less<int>, int>::value);
|
||||||
|
}
|
||||||
SECTION("sizeof") {
|
SECTION("sizeof") {
|
||||||
REQUIRE(sizeof(flat_multiset<int>) == sizeof(std::vector<int>));
|
REQUIRE(sizeof(flat_multiset<int>) == sizeof(std::vector<int>));
|
||||||
|
|
||||||
@@ -382,6 +389,21 @@ TEST_CASE("flat_multiset") {
|
|||||||
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 4);
|
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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") {
|
SECTION("observers") {
|
||||||
struct my_less {
|
struct my_less {
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
@@ -9,6 +9,9 @@
|
|||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
#include <flat.hpp/flat_set.hpp>
|
#include <flat.hpp/flat_set.hpp>
|
||||||
using namespace flat_hpp;
|
using namespace flat_hpp;
|
||||||
|
|
||||||
@@ -54,6 +57,10 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("flat_set") {
|
TEST_CASE("flat_set") {
|
||||||
|
SECTION("detail") {
|
||||||
|
STATIC_REQUIRE(detail::is_transparent<std::less<>, int>::value);
|
||||||
|
STATIC_REQUIRE_FALSE(detail::is_transparent<std::less<int>, int>::value);
|
||||||
|
}
|
||||||
SECTION("sizeof") {
|
SECTION("sizeof") {
|
||||||
REQUIRE(sizeof(flat_set<int>) == sizeof(std::vector<int>));
|
REQUIRE(sizeof(flat_set<int>) == sizeof(std::vector<int>));
|
||||||
|
|
||||||
@@ -380,6 +387,21 @@ TEST_CASE("flat_set") {
|
|||||||
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 3);
|
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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") {
|
SECTION("observers") {
|
||||||
struct my_less {
|
struct my_less {
|
||||||
int i;
|
int i;
|
||||||
|
|||||||
Reference in New Issue
Block a user