removed unused methods(BeginPlay, Tick) and added rider plugin
This commit is contained in:
21
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/LICENSE
vendored
Normal file
21
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/LICENSE
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Tessil
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
242
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/README.md
vendored
Normal file
242
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/README.md
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
[](https://travis-ci.org/Tessil/ordered-map) [](https://ci.appveyor.com/project/Tessil/ordered-map/branch/master)
|
||||
|
||||
## C++ hash map and hash set which preserves the order of insertion
|
||||
|
||||
The ordered-map library provides a hash map and a hash set which preserve the order of insertion in a way similar to Python's [OrderedDict](https://docs.python.org/3/library/collections.html#collections.OrderedDict). When iterating over the map, the values will be returned in the same order as they were inserted.
|
||||
|
||||
The values are stored contiguously in an underlying structure, no holes in-between values even after an erase operation. By default a `std::deque` is used for this structure, but it's also possible to use a `std::vector`. This structure is directly accessible through the `values_container()` method and if the structure is a `std::vector`, a `data()` method is also provided to easily interact with C APIs.
|
||||
|
||||
To resolve collisions on hashes, the library uses linear robin hood probing with backward shift deletion.
|
||||
|
||||
The library provides a behaviour similar to a `std::deque/std::vector` with unique values but with an average time complexity of O(1) for lookups and an amortised time complexity of O(1) for insertions. This comes at the price of a little higher memory footprint (8 bytes per bucket by default).
|
||||
|
||||
Two classes are provided: `tsl::ordered_map` and `tsl::ordered_set`.
|
||||
|
||||
**Note**: The library uses a power of two for the size of its buckets array to take advantage of the [fast modulo](https://en.wikipedia.org/wiki/Modulo_operation#Performance_issues). For good performances, it requires the hash table to have a well-distributed hash function. If you encounter performance issues check your hash function.
|
||||
|
||||
### Key features
|
||||
|
||||
- Header-only library, just add the [include](include/) directory to your include path and you are ready to go. If you use CMake, you can also use the `tsl::ordered_map` exported target from the [CMakeLists.txt](CMakeLists.txt).
|
||||
- Values are stored in the same order as the insertion order. The library provides a direct access to the underlying structure which stores the values.
|
||||
- O(1) average time complexity for lookups with performances similar to `std::unordered_map` but with faster insertions and reduced memory usage (see [benchmark](https://tessil.github.io/2016/08/29/benchmark-hopscotch-map.html) for details).
|
||||
- Provide random access iterators and also reverse iterators.
|
||||
- Support for heterogeneous lookups allowing the usage of `find` with a type different than `Key` (e.g. if you have a map that uses `std::unique_ptr<foo>` as key, you can use a `foo*` or a `std::uintptr_t` as key parameter to `find` without constructing a `std::unique_ptr<foo>`, see [example](#heterogeneous-lookups)).
|
||||
- If the hash is known before a lookup, it is possible to pass it as parameter to speed-up the lookup (see `precalculated_hash` parameter in [API](https://tessil.github.io/ordered-map/classtsl_1_1ordered__map.html#a7fcde27edc6697a0b127f4b1aefa8a7d)).
|
||||
- The library can be used with exceptions disabled (through `-fno-exceptions` option on Clang and GCC, without an `/EH` option on MSVC or simply by defining `TSL_NO_EXCEPTIONS`). `std::terminate` is used in replacement of the `throw` instruction when exceptions are disabled.
|
||||
- API closely similar to `std::unordered_map` and `std::unordered_set`.
|
||||
|
||||
### Differences compare to `std::unordered_map`
|
||||
`tsl::ordered_map` tries to have an interface similar to `std::unordered_map`, but some differences exist.
|
||||
- The iterators are `RandomAccessIterator`.
|
||||
- Iterator invalidation behaves in a way closer to `std::vector` and `std::deque` (see [API](https://tessil.github.io/ordered-map/classtsl_1_1ordered__map.html#details) for details). If you use `std::vector` as `ValueTypeContainer`, you can use `reserve()` to preallocate some space and avoid the invalidation of the iterators on insert.
|
||||
- Slow `erase()` operation, it has a complexity of O(n). A faster O(1) version `unordered_erase()` exists, but it breaks the insertion order (see [API](https://tessil.github.io/ordered-map/classtsl_1_1ordered__map.html#a9f94a7889fa7fa92eea41ca63b3f98a4) for details). An O(1) `pop_back()` is also available.
|
||||
- The equality oprators `operator==` and `operator!=` are order dependent. Two `tsl::ordered_map` with the same values but inserted in a different order don't compare equal.
|
||||
- For iterators, `operator*()` and `operator->()` return a reference and a pointer to `const std::pair<Key, T>` instead of `std::pair<const Key, T>` making the value `T` not modifiable. To modify the value you have to call the `value()` method of the iterator to get a mutable reference. Example:
|
||||
```c++
|
||||
tsl::ordered_map<int, int> map = {{1, 1}, {2, 1}, {3, 1}};
|
||||
for(auto it = map.begin(); it != map.end(); ++it) {
|
||||
//it->second = 2; // Illegal
|
||||
it.value() = 2; // Ok
|
||||
}
|
||||
```
|
||||
- By default the map can only hold up to 2<sup>32</sup> - 1 values, that is 4 294 967 295 values. This can be raised through the `IndexType` class template parameter, check the [API](https://tessil.github.io/ordered-map/classtsl_1_1ordered__map.html#details) for details.
|
||||
- No support for some bucket related methods (like `bucket_size`, `bucket`, ...).
|
||||
|
||||
|
||||
Thread-safety guarantee is the same as `std::unordered_map` (i.e. possible to have multiple concurrent readers with no writer).
|
||||
|
||||
Concerning the strong exception guarantee, it holds only if `ValueContainer::emplace_back` has the strong exception guarantee (which is true for `std::vector` and `std::deque` as long as the type `T` is not a move-only type with a move constructor that may throw an exception, see [details](http://en.cppreference.com/w/cpp/container/vector/emplace_back#Exceptions)).
|
||||
|
||||
These differences also apply between `std::unordered_set` and `tsl::ordered_set`.
|
||||
|
||||
|
||||
### Installation
|
||||
|
||||
To use ordered-map, just add the [include](include/) directory to your include path. It is a **header-only** library.
|
||||
|
||||
If you use CMake, you can also use the `tsl::ordered_map` exported target from the [CMakeLists.txt](CMakeLists.txt) with `target_link_libraries`.
|
||||
```cmake
|
||||
# Example where the ordered-map project is stored in a third-party directory
|
||||
add_subdirectory(third-party/ordered-map)
|
||||
target_link_libraries(your_target PRIVATE tsl::ordered_map)
|
||||
```
|
||||
|
||||
The code should work with any C++11 standard-compliant compiler and has been tested with GCC 4.8.4, Clang 3.5.0 and Visual Studio 2015.
|
||||
|
||||
To run the tests you will need the Boost Test library and CMake.
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Tessil/ordered-map.git
|
||||
cd ordered-map/tests
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
./tsl_ordered_map_tests
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
The API can be found [here](https://tessil.github.io/ordered-map/).
|
||||
|
||||
### Example
|
||||
|
||||
```c++
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <tsl/ordered_map.h>
|
||||
#include <tsl/ordered_set.h>
|
||||
|
||||
int main() {
|
||||
tsl::ordered_map<char, int> map = {{'d', 1}, {'a', 2}, {'g', 3}};
|
||||
map.insert({'b', 4});
|
||||
map['h'] = 5;
|
||||
map['e'] = 6;
|
||||
|
||||
map.erase('a');
|
||||
|
||||
|
||||
// {d, 1} {g, 3} {b, 4} {h, 5} {e, 6}
|
||||
for(const auto& key_value : map) {
|
||||
std::cout << "{" << key_value.first << ", " << key_value.second << "}" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
map.unordered_erase('b');
|
||||
|
||||
// Break order: {d, 1} {g, 3} {e, 6} {h, 5}
|
||||
for(const auto& key_value : map) {
|
||||
std::cout << "{" << key_value.first << ", " << key_value.second << "}" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
for(auto it = map.begin(); it != map.end(); ++it) {
|
||||
//it->second += 2; // Not valid.
|
||||
it.value() += 2;
|
||||
}
|
||||
|
||||
|
||||
if(map.find('d') != map.end()) {
|
||||
std::cout << "Found 'd'." << std::endl;
|
||||
}
|
||||
|
||||
const std::size_t precalculated_hash = std::hash<char>()('d');
|
||||
// If we already know the hash beforehand, we can pass it as argument to speed-up the lookup.
|
||||
if(map.find('d', precalculated_hash) != map.end()) {
|
||||
std::cout << "Found 'd' with hash " << precalculated_hash << "." << std::endl;
|
||||
}
|
||||
|
||||
|
||||
tsl::ordered_set<char, std::hash<char>, std::equal_to<char>,
|
||||
std::allocator<char>, std::vector<char>> set;
|
||||
set.reserve(6);
|
||||
|
||||
set = {'3', '4', '9', '2'};
|
||||
set.erase('2');
|
||||
set.insert('1');
|
||||
set.insert('\0');
|
||||
|
||||
set.pop_back();
|
||||
set.insert({'0', '\0'});
|
||||
|
||||
// Get raw buffer for C API: 34910
|
||||
std::cout << atoi(set.data()) << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
#### Heterogeneous lookup
|
||||
|
||||
Heterogeneous overloads allow the usage of other types than `Key` for lookup and erase operations as long as the used types are hashable and comparable to `Key`.
|
||||
|
||||
To activate the heterogeneous overloads in `tsl::ordered_map/set`, the qualified-id `KeyEqual::is_transparent` must be valid. It works the same way as for [`std::map::find`](http://en.cppreference.com/w/cpp/container/map/find). You can either use [`std::equal_to<>`](http://en.cppreference.com/w/cpp/utility/functional/equal_to_void) or define your own function object.
|
||||
|
||||
Both `KeyEqual` and `Hash` will need to be able to deal with the different types.
|
||||
|
||||
```c++
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <tsl/ordered_map.h>
|
||||
|
||||
|
||||
|
||||
struct employee {
|
||||
employee(int id, std::string name) : m_id(id), m_name(std::move(name)) {
|
||||
}
|
||||
|
||||
// Either we include the comparators in the class and we use `std::equal_to<>`...
|
||||
friend bool operator==(const employee& empl, int empl_id) {
|
||||
return empl.m_id == empl_id;
|
||||
}
|
||||
|
||||
friend bool operator==(int empl_id, const employee& empl) {
|
||||
return empl_id == empl.m_id;
|
||||
}
|
||||
|
||||
friend bool operator==(const employee& empl1, const employee& empl2) {
|
||||
return empl1.m_id == empl2.m_id;
|
||||
}
|
||||
|
||||
|
||||
int m_id;
|
||||
std::string m_name;
|
||||
};
|
||||
|
||||
// ... or we implement a separate class to compare employees.
|
||||
struct equal_employee {
|
||||
using is_transparent = void;
|
||||
|
||||
bool operator()(const employee& empl, int empl_id) const {
|
||||
return empl.m_id == empl_id;
|
||||
}
|
||||
|
||||
bool operator()(int empl_id, const employee& empl) const {
|
||||
return empl_id == empl.m_id;
|
||||
}
|
||||
|
||||
bool operator()(const employee& empl1, const employee& empl2) const {
|
||||
return empl1.m_id == empl2.m_id;
|
||||
}
|
||||
};
|
||||
|
||||
struct hash_employee {
|
||||
std::size_t operator()(const employee& empl) const {
|
||||
return std::hash<int>()(empl.m_id);
|
||||
}
|
||||
|
||||
std::size_t operator()(int id) const {
|
||||
return std::hash<int>()(id);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main() {
|
||||
// Use std::equal_to<> which will automatically deduce and forward the parameters
|
||||
tsl::ordered_map<employee, int, hash_employee, std::equal_to<>> map;
|
||||
map.insert({employee(1, "John Doe"), 2001});
|
||||
map.insert({employee(2, "Jane Doe"), 2002});
|
||||
map.insert({employee(3, "John Smith"), 2003});
|
||||
|
||||
// John Smith 2003
|
||||
auto it = map.find(3);
|
||||
if(it != map.end()) {
|
||||
std::cout << it->first.m_name << " " << it->second << std::endl;
|
||||
}
|
||||
|
||||
map.erase(1);
|
||||
|
||||
|
||||
|
||||
// Use a custom KeyEqual which has an is_transparent member type
|
||||
tsl::ordered_map<employee, int, hash_employee, equal_employee> map2;
|
||||
map2.insert({employee(4, "Johnny Doe"), 2004});
|
||||
|
||||
// 2004
|
||||
std::cout << map2.at(4) << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
### License
|
||||
|
||||
The code is licensed under the MIT license, see the [LICENSE file](LICENSE) for details.
|
||||
1444
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/include/tsl/ordered_hash.h
vendored
Normal file
1444
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/include/tsl/ordered_hash.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
793
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/include/tsl/ordered_map.h
vendored
Normal file
793
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/include/tsl/ordered_map.h
vendored
Normal file
@@ -0,0 +1,793 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 Tessil
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#ifndef TSL_ORDERED_MAP_H
|
||||
#define TSL_ORDERED_MAP_H
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "ordered_hash.h"
|
||||
|
||||
|
||||
namespace tsl {
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of an hash map using open adressing with robin hood with backshift delete to resolve collisions.
|
||||
*
|
||||
* The particularity of this hash map is that it remembers the order in which the elements were added and
|
||||
* provide a way to access the structure which stores these values through the 'values_container()' method.
|
||||
* The used container is defined by ValueTypeContainer, by default a std::deque is used (grows faster) but
|
||||
* a std::vector may be used. In this case the map provides a 'data()' method which give a direct access
|
||||
* to the memory used to store the values (which can be usefull to communicate with C API's).
|
||||
*
|
||||
* The Key and T must be copy constructible and/or move constructible. To use `unordered_erase` they both
|
||||
* must be swappable.
|
||||
*
|
||||
* The behaviour of the hash map is undefinded if the destructor of Key or T throws an exception.
|
||||
*
|
||||
* By default the maximum size of a map is limited to 2^32 - 1 values, if needed this can be changed through
|
||||
* the IndexType template parameter. Using an `uint64_t` will raise this limit to 2^64 - 1 values but each
|
||||
* bucket will use 16 bytes instead of 8 bytes in addition to the space needed to store the values.
|
||||
*
|
||||
* Iterators invalidation:
|
||||
* - clear, operator=, reserve, rehash: always invalidate the iterators (also invalidate end()).
|
||||
* - insert, emplace, emplace_hint, operator[]: when a std::vector is used as ValueTypeContainer
|
||||
* and if size() < capacity(), only end().
|
||||
* Otherwise all the iterators are invalidated if an insert occurs.
|
||||
* - erase, unordered_erase: when a std::vector is used as ValueTypeContainer invalidate the iterator of
|
||||
* the erased element and all the ones after the erased element (including end()).
|
||||
* Otherwise all the iterators are invalidated if an erase occurs.
|
||||
*/
|
||||
template<class Key,
|
||||
class T,
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<std::pair<Key, T>>,
|
||||
class ValueTypeContainer = std::deque<std::pair<Key, T>, Allocator>,
|
||||
class IndexType = std::uint_least32_t>
|
||||
class ordered_map {
|
||||
private:
|
||||
template<typename U>
|
||||
using has_is_transparent = tsl::detail_ordered_hash::has_is_transparent<U>;
|
||||
|
||||
class KeySelect {
|
||||
public:
|
||||
using key_type = Key;
|
||||
|
||||
const key_type& operator()(const std::pair<Key, T>& key_value) const noexcept {
|
||||
return key_value.first;
|
||||
}
|
||||
|
||||
key_type& operator()(std::pair<Key, T>& key_value) noexcept {
|
||||
return key_value.first;
|
||||
}
|
||||
};
|
||||
|
||||
class ValueSelect {
|
||||
public:
|
||||
using value_type = T;
|
||||
|
||||
const value_type& operator()(const std::pair<Key, T>& key_value) const noexcept {
|
||||
return key_value.second;
|
||||
}
|
||||
|
||||
value_type& operator()(std::pair<Key, T>& key_value) noexcept {
|
||||
return key_value.second;
|
||||
}
|
||||
};
|
||||
|
||||
using ht = detail_ordered_hash::ordered_hash<std::pair<Key, T>, KeySelect, ValueSelect,
|
||||
Hash, KeyEqual, Allocator, ValueTypeContainer, IndexType>;
|
||||
|
||||
public:
|
||||
using key_type = typename ht::key_type;
|
||||
using mapped_type = T;
|
||||
using value_type = typename ht::value_type;
|
||||
using size_type = typename ht::size_type;
|
||||
using difference_type = typename ht::difference_type;
|
||||
using hasher = typename ht::hasher;
|
||||
using key_equal = typename ht::key_equal;
|
||||
using allocator_type = typename ht::allocator_type;
|
||||
using reference = typename ht::reference;
|
||||
using const_reference = typename ht::const_reference;
|
||||
using pointer = typename ht::pointer;
|
||||
using const_pointer = typename ht::const_pointer;
|
||||
using iterator = typename ht::iterator;
|
||||
using const_iterator = typename ht::const_iterator;
|
||||
using reverse_iterator = typename ht::reverse_iterator;
|
||||
using const_reverse_iterator = typename ht::const_reverse_iterator;
|
||||
|
||||
using values_container_type = typename ht::values_container_type;
|
||||
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
ordered_map(): ordered_map(ht::DEFAULT_INIT_BUCKETS_SIZE) {
|
||||
}
|
||||
|
||||
explicit ordered_map(size_type bucket_count,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()):
|
||||
m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_map(size_type bucket_count,
|
||||
const Allocator& alloc): ordered_map(bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_map(size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc): ordered_map(bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
explicit ordered_map(const Allocator& alloc): ordered_map(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
ordered_map(InputIt first, InputIt last,
|
||||
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()): ordered_map(bucket_count, hash, equal, alloc)
|
||||
{
|
||||
insert(first, last);
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
ordered_map(InputIt first, InputIt last,
|
||||
size_type bucket_count,
|
||||
const Allocator& alloc): ordered_map(first, last, bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
ordered_map(InputIt first, InputIt last,
|
||||
size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc): ordered_map(first, last, bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_map(std::initializer_list<value_type> init,
|
||||
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()):
|
||||
ordered_map(init.begin(), init.end(), bucket_count, hash, equal, alloc)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_map(std::initializer_list<value_type> init,
|
||||
size_type bucket_count,
|
||||
const Allocator& alloc):
|
||||
ordered_map(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_map(std::initializer_list<value_type> init,
|
||||
size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc):
|
||||
ordered_map(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ordered_map& operator=(std::initializer_list<value_type> ilist) {
|
||||
m_ht.clear();
|
||||
|
||||
m_ht.reserve(ilist.size());
|
||||
m_ht.insert(ilist.begin(), ilist.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const { return m_ht.get_allocator(); }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Iterators
|
||||
*/
|
||||
iterator begin() noexcept { return m_ht.begin(); }
|
||||
const_iterator begin() const noexcept { return m_ht.begin(); }
|
||||
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
|
||||
|
||||
iterator end() noexcept { return m_ht.end(); }
|
||||
const_iterator end() const noexcept { return m_ht.end(); }
|
||||
const_iterator cend() const noexcept { return m_ht.cend(); }
|
||||
|
||||
reverse_iterator rbegin() noexcept { return m_ht.rbegin(); }
|
||||
const_reverse_iterator rbegin() const noexcept { return m_ht.rbegin(); }
|
||||
const_reverse_iterator rcbegin() const noexcept { return m_ht.rcbegin(); }
|
||||
|
||||
reverse_iterator rend() noexcept { return m_ht.rend(); }
|
||||
const_reverse_iterator rend() const noexcept { return m_ht.rend(); }
|
||||
const_reverse_iterator rcend() const noexcept { return m_ht.rcend(); }
|
||||
|
||||
|
||||
/*
|
||||
* Capacity
|
||||
*/
|
||||
bool empty() const noexcept { return m_ht.empty(); }
|
||||
size_type size() const noexcept { return m_ht.size(); }
|
||||
size_type max_size() const noexcept { return m_ht.max_size(); }
|
||||
|
||||
/*
|
||||
* Modifiers
|
||||
*/
|
||||
void clear() noexcept { m_ht.clear(); }
|
||||
|
||||
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& value) { return m_ht.insert(value); }
|
||||
|
||||
template<class P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
|
||||
std::pair<iterator, bool> insert(P&& value) { return m_ht.emplace(std::forward<P>(value)); }
|
||||
|
||||
std::pair<iterator, bool> insert(value_type&& value) { return m_ht.insert(std::move(value)); }
|
||||
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& value) {
|
||||
return m_ht.insert(hint, value);
|
||||
}
|
||||
|
||||
template<class P, typename std::enable_if<std::is_constructible<value_type, P&&>::value>::type* = nullptr>
|
||||
iterator insert(const_iterator hint, P&& value) {
|
||||
return m_ht.emplace_hint(hint, std::forward<P>(value));
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, value_type&& value) {
|
||||
return m_ht.insert(hint, std::move(value));
|
||||
}
|
||||
|
||||
|
||||
template<class InputIt>
|
||||
void insert(InputIt first, InputIt last) { m_ht.insert(first, last); }
|
||||
void insert(std::initializer_list<value_type> ilist) { m_ht.insert(ilist.begin(), ilist.end()); }
|
||||
|
||||
|
||||
|
||||
|
||||
template<class M>
|
||||
std::pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj) {
|
||||
return m_ht.insert_or_assign(k, std::forward<M>(obj));
|
||||
}
|
||||
|
||||
template<class M>
|
||||
std::pair<iterator, bool> insert_or_assign(key_type&& k, M&& obj) {
|
||||
return m_ht.insert_or_assign(std::move(k), std::forward<M>(obj));
|
||||
}
|
||||
|
||||
|
||||
template<class M>
|
||||
iterator insert_or_assign(const_iterator hint, const key_type& k, M&& obj) {
|
||||
return m_ht.insert_or_assign(hint, k, std::forward<M>(obj));
|
||||
}
|
||||
|
||||
template<class M>
|
||||
iterator insert_or_assign(const_iterator hint, key_type&& k, M&& obj) {
|
||||
return m_ht.insert_or_assign(hint, std::move(k), std::forward<M>(obj));
|
||||
}
|
||||
|
||||
/**
|
||||
* Due to the way elements are stored, emplace will need to move or copy the key-value once.
|
||||
* The method is equivalent to insert(value_type(std::forward<Args>(args)...));
|
||||
*
|
||||
* Mainly here for compatibility with the std::unordered_map interface.
|
||||
*/
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args) { return m_ht.emplace(std::forward<Args>(args)...); }
|
||||
|
||||
/**
|
||||
* Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
|
||||
* The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));
|
||||
*
|
||||
* Mainly here for compatibility with the std::unordered_map interface.
|
||||
*/
|
||||
template <class... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args) {
|
||||
return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> try_emplace(const key_type& k, Args&&... args) {
|
||||
return m_ht.try_emplace(k, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> try_emplace(key_type&& k, Args&&... args) {
|
||||
return m_ht.try_emplace(std::move(k), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
iterator try_emplace(const_iterator hint, const key_type& k, Args&&... args) {
|
||||
return m_ht.try_emplace(hint, k, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
iterator try_emplace(const_iterator hint, key_type&& k, Args&&... args) {
|
||||
return m_ht.try_emplace(hint, std::move(k), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* When erasing an element, the insert order will be preserved and no holes will be present in the container
|
||||
* returned by 'values_container()'.
|
||||
*
|
||||
* The method is in O(n), if the order is not important 'unordered_erase(...)' method is faster with an O(1)
|
||||
* average complexity.
|
||||
*/
|
||||
iterator erase(iterator pos) { return m_ht.erase(pos); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*/
|
||||
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*/
|
||||
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*/
|
||||
size_type erase(const key_type& key) { return m_ht.erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
|
||||
*/
|
||||
size_type erase(const key_type& key, std::size_t precalculated_hash) {
|
||||
return m_ht.erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type erase(const K& key) { return m_ht.erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(const key_type& key, std::size_t precalculated_hash)
|
||||
*
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type erase(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void swap(ordered_map& other) { other.m_ht.swap(m_ht); }
|
||||
|
||||
/*
|
||||
* Lookup
|
||||
*/
|
||||
T& at(const Key& key) { return m_ht.at(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
T& at(const Key& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
|
||||
|
||||
|
||||
const T& at(const Key& key) const { return m_ht.at(key); }
|
||||
|
||||
/**
|
||||
* @copydoc at(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
const T& at(const Key& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
|
||||
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
T& at(const K& key) { return m_ht.at(key); }
|
||||
|
||||
/**
|
||||
* @copydoc at(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
T& at(const K& key, std::size_t precalculated_hash) { return m_ht.at(key, precalculated_hash); }
|
||||
|
||||
/**
|
||||
* @copydoc at(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const T& at(const K& key) const { return m_ht.at(key); }
|
||||
|
||||
/**
|
||||
* @copydoc at(const K& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const T& at(const K& key, std::size_t precalculated_hash) const { return m_ht.at(key, precalculated_hash); }
|
||||
|
||||
|
||||
|
||||
T& operator[](const Key& key) { return m_ht[key]; }
|
||||
T& operator[](Key&& key) { return m_ht[std::move(key)]; }
|
||||
|
||||
|
||||
|
||||
size_type count(const Key& key) const { return m_ht.count(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
size_type count(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.count(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type count(const K& key) const { return m_ht.count(key); }
|
||||
|
||||
/**
|
||||
* @copydoc count(const K& key) const
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type count(const K& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.count(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
iterator find(const Key& key) { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
const_iterator find(const Key& key) const { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
const_iterator find(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.find(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
iterator find(const K& key) { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const_iterator find(const K& key) const { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const_iterator find(const K& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.find(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Bucket interface
|
||||
*/
|
||||
size_type bucket_count() const { return m_ht.bucket_count(); }
|
||||
size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
|
||||
|
||||
|
||||
/*
|
||||
* Hash policy
|
||||
*/
|
||||
float load_factor() const { return m_ht.load_factor(); }
|
||||
float max_load_factor() const { return m_ht.max_load_factor(); }
|
||||
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
|
||||
|
||||
void rehash(size_type count) { m_ht.rehash(count); }
|
||||
void reserve(size_type count) { m_ht.reserve(count); }
|
||||
|
||||
|
||||
/*
|
||||
* Observers
|
||||
*/
|
||||
hasher hash_function() const { return m_ht.hash_function(); }
|
||||
key_equal key_eq() const { return m_ht.key_eq(); }
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Other
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a const_iterator to an iterator.
|
||||
*/
|
||||
iterator mutable_iterator(const_iterator pos) {
|
||||
return m_ht.mutable_iterator(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires index <= size().
|
||||
*
|
||||
* Return an iterator to the element at index. Return end() if index == size().
|
||||
*/
|
||||
iterator nth(size_type index) { return m_ht.nth(index); }
|
||||
|
||||
/**
|
||||
* @copydoc nth(size_type index)
|
||||
*/
|
||||
const_iterator nth(size_type index) const { return m_ht.nth(index); }
|
||||
|
||||
|
||||
/**
|
||||
* Return const_reference to the first element. Requires the container to not be empty.
|
||||
*/
|
||||
const_reference front() const { return m_ht.front(); }
|
||||
|
||||
/**
|
||||
* Return const_reference to the last element. Requires the container to not be empty.
|
||||
*/
|
||||
const_reference back() const { return m_ht.back(); }
|
||||
|
||||
|
||||
/**
|
||||
* Only available if ValueTypeContainer is a std::vector. Same as calling 'values_container().data()'.
|
||||
*/
|
||||
template<class U = values_container_type, typename std::enable_if<tsl::detail_ordered_hash::is_vector<U>::value>::type* = nullptr>
|
||||
const typename values_container_type::value_type* data() const noexcept { return m_ht.data(); }
|
||||
|
||||
/**
|
||||
* Return the container in which the values are stored. The values are in the same order as the insertion order
|
||||
* and are contiguous in the structure, no holes (size() == values_container().size()).
|
||||
*/
|
||||
const values_container_type& values_container() const noexcept { return m_ht.values_container(); }
|
||||
|
||||
template<class U = values_container_type, typename std::enable_if<tsl::detail_ordered_hash::is_vector<U>::value>::type* = nullptr>
|
||||
size_type capacity() const noexcept { return m_ht.capacity(); }
|
||||
|
||||
void shrink_to_fit() { m_ht.shrink_to_fit(); }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Insert the value before pos shifting all the elements on the right of pos (including pos) one position
|
||||
* to the right.
|
||||
*
|
||||
* Amortized linear time-complexity in the distance between pos and end().
|
||||
*/
|
||||
std::pair<iterator, bool> insert_at_position(const_iterator pos, const value_type& value) {
|
||||
return m_ht.insert_at_position(pos, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc insert_at_position(const_iterator pos, const value_type& value)
|
||||
*/
|
||||
std::pair<iterator, bool> insert_at_position(const_iterator pos, value_type&& value) {
|
||||
return m_ht.insert_at_position(pos, std::move(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc insert_at_position(const_iterator pos, const value_type& value)
|
||||
*
|
||||
* Same as insert_at_position(pos, value_type(std::forward<Args>(args)...), mainly
|
||||
* here for coherence.
|
||||
*/
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> emplace_at_position(const_iterator pos, Args&&... args) {
|
||||
return m_ht.emplace_at_position(pos, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc insert_at_position(const_iterator pos, const value_type& value)
|
||||
*/
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> try_emplace_at_position(const_iterator pos, const key_type& k, Args&&... args) {
|
||||
return m_ht.try_emplace_at_position(pos, k, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc insert_at_position(const_iterator pos, const value_type& value)
|
||||
*/
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> try_emplace_at_position(const_iterator pos, key_type&& k, Args&&... args) {
|
||||
return m_ht.try_emplace_at_position(pos, std::move(k), std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pop_back() { m_ht.pop_back(); }
|
||||
|
||||
/**
|
||||
* Faster erase operation with an O(1) average complexity but it doesn't preserve the insertion order.
|
||||
*
|
||||
* If an erasure occurs, the last element of the map will take the place of the erased element.
|
||||
*/
|
||||
iterator unordered_erase(iterator pos) { return m_ht.unordered_erase(pos); }
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(iterator pos)
|
||||
*/
|
||||
iterator unordered_erase(const_iterator pos) { return m_ht.unordered_erase(pos); }
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(iterator pos)
|
||||
*/
|
||||
size_type unordered_erase(const key_type& key) { return m_ht.unordered_erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(iterator pos)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
size_type unordered_erase(const key_type& key, std::size_t precalculated_hash) {
|
||||
return m_ht.unordered_erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(iterator pos)
|
||||
*
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type unordered_erase(const K& key) { return m_ht.unordered_erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type unordered_erase(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.unordered_erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
friend bool operator==(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht == rhs.m_ht; }
|
||||
friend bool operator!=(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht != rhs.m_ht; }
|
||||
friend bool operator<(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht < rhs.m_ht; }
|
||||
friend bool operator<=(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht <= rhs.m_ht; }
|
||||
friend bool operator>(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht > rhs.m_ht; }
|
||||
friend bool operator>=(const ordered_map& lhs, const ordered_map& rhs) { return lhs.m_ht >= rhs.m_ht; }
|
||||
|
||||
friend void swap(ordered_map& lhs, ordered_map& rhs) { lhs.swap(rhs); }
|
||||
|
||||
private:
|
||||
ht m_ht;
|
||||
};
|
||||
|
||||
} // end namespace tsl
|
||||
|
||||
#endif
|
||||
648
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/include/tsl/ordered_set.h
vendored
Normal file
648
Plugins/Developer/RiderLink/Source/RD/thirdparty/ordered-map/include/tsl/ordered_set.h
vendored
Normal file
@@ -0,0 +1,648 @@
|
||||
/**
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2017 Tessil
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
#ifndef TSL_ORDERED_SET_H
|
||||
#define TSL_ORDERED_SET_H
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <deque>
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "ordered_hash.h"
|
||||
|
||||
|
||||
namespace tsl {
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of an hash set using open adressing with robin hood with backshift delete to resolve collisions.
|
||||
*
|
||||
* The particularity of this hash set is that it remembers the order in which the elements were added and
|
||||
* provide a way to access the structure which stores these values through the 'values_container()' method.
|
||||
* The used container is defined by ValueTypeContainer, by default a std::deque is used (grows faster) but
|
||||
* a std::vector may be used. In this case the set provides a 'data()' method which give a direct access
|
||||
* to the memory used to store the values (which can be usefull to communicate with C API's).
|
||||
*
|
||||
* The Key must be copy constructible and/or move constructible. To use `unordered_erase` it also must be swappable.
|
||||
*
|
||||
* The behaviour of the hash set is undefinded if the destructor of Key throws an exception.
|
||||
*
|
||||
* By default the maximum size of a set is limited to 2^32 - 1 values, if needed this can be changed through
|
||||
* the IndexType template parameter. Using an `uint64_t` will raise this limit to 2^64 - 1 values but each
|
||||
* bucket will use 16 bytes instead of 8 bytes in addition to the space needed to store the values.
|
||||
*
|
||||
* Iterators invalidation:
|
||||
* - clear, operator=, reserve, rehash: always invalidate the iterators (also invalidate end()).
|
||||
* - insert, emplace, emplace_hint, operator[]: when a std::vector is used as ValueTypeContainer
|
||||
* and if size() < capacity(), only end().
|
||||
* Otherwise all the iterators are invalidated if an insert occurs.
|
||||
* - erase, unordered_erase: when a std::vector is used as ValueTypeContainer invalidate the iterator of
|
||||
* the erased element and all the ones after the erased element (including end()).
|
||||
* Otherwise all the iterators are invalidated if an erase occurs.
|
||||
*/
|
||||
template<class Key,
|
||||
class Hash = std::hash<Key>,
|
||||
class KeyEqual = std::equal_to<Key>,
|
||||
class Allocator = std::allocator<Key>,
|
||||
class ValueTypeContainer = std::deque<Key, Allocator>,
|
||||
class IndexType = std::uint_least32_t>
|
||||
class ordered_set {
|
||||
private:
|
||||
template<typename U>
|
||||
using has_is_transparent = tsl::detail_ordered_hash::has_is_transparent<U>;
|
||||
|
||||
class KeySelect {
|
||||
public:
|
||||
using key_type = Key;
|
||||
|
||||
const key_type& operator()(const Key& key) const noexcept {
|
||||
return key;
|
||||
}
|
||||
|
||||
key_type& operator()(Key& key) noexcept {
|
||||
return key;
|
||||
}
|
||||
};
|
||||
|
||||
using ht = detail_ordered_hash::ordered_hash<Key, KeySelect, void,
|
||||
Hash, KeyEqual, Allocator, ValueTypeContainer, IndexType>;
|
||||
|
||||
public:
|
||||
using key_type = typename ht::key_type;
|
||||
using value_type = typename ht::value_type;
|
||||
using size_type = typename ht::size_type;
|
||||
using difference_type = typename ht::difference_type;
|
||||
using hasher = typename ht::hasher;
|
||||
using key_equal = typename ht::key_equal;
|
||||
using allocator_type = typename ht::allocator_type;
|
||||
using reference = typename ht::reference;
|
||||
using const_reference = typename ht::const_reference;
|
||||
using pointer = typename ht::pointer;
|
||||
using const_pointer = typename ht::const_pointer;
|
||||
using iterator = typename ht::iterator;
|
||||
using const_iterator = typename ht::const_iterator;
|
||||
using reverse_iterator = typename ht::reverse_iterator;
|
||||
using const_reverse_iterator = typename ht::const_reverse_iterator;
|
||||
|
||||
using values_container_type = typename ht::values_container_type;
|
||||
|
||||
|
||||
/*
|
||||
* Constructors
|
||||
*/
|
||||
ordered_set(): ordered_set(ht::DEFAULT_INIT_BUCKETS_SIZE) {
|
||||
}
|
||||
|
||||
explicit ordered_set(size_type bucket_count,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()):
|
||||
m_ht(bucket_count, hash, equal, alloc, ht::DEFAULT_MAX_LOAD_FACTOR)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_set(size_type bucket_count,
|
||||
const Allocator& alloc): ordered_set(bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_set(size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc): ordered_set(bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
explicit ordered_set(const Allocator& alloc): ordered_set(ht::DEFAULT_INIT_BUCKETS_SIZE, alloc) {
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
ordered_set(InputIt first, InputIt last,
|
||||
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()): ordered_set(bucket_count, hash, equal, alloc)
|
||||
{
|
||||
insert(first, last);
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
ordered_set(InputIt first, InputIt last,
|
||||
size_type bucket_count,
|
||||
const Allocator& alloc): ordered_set(first, last, bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
ordered_set(InputIt first, InputIt last,
|
||||
size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc): ordered_set(first, last, bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_set(std::initializer_list<value_type> init,
|
||||
size_type bucket_count = ht::DEFAULT_INIT_BUCKETS_SIZE,
|
||||
const Hash& hash = Hash(),
|
||||
const KeyEqual& equal = KeyEqual(),
|
||||
const Allocator& alloc = Allocator()):
|
||||
ordered_set(init.begin(), init.end(), bucket_count, hash, equal, alloc)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_set(std::initializer_list<value_type> init,
|
||||
size_type bucket_count,
|
||||
const Allocator& alloc):
|
||||
ordered_set(init.begin(), init.end(), bucket_count, Hash(), KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
ordered_set(std::initializer_list<value_type> init,
|
||||
size_type bucket_count,
|
||||
const Hash& hash,
|
||||
const Allocator& alloc):
|
||||
ordered_set(init.begin(), init.end(), bucket_count, hash, KeyEqual(), alloc)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ordered_set& operator=(std::initializer_list<value_type> ilist) {
|
||||
m_ht.clear();
|
||||
|
||||
m_ht.reserve(ilist.size());
|
||||
m_ht.insert(ilist.begin(), ilist.end());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
allocator_type get_allocator() const { return m_ht.get_allocator(); }
|
||||
|
||||
|
||||
/*
|
||||
* Iterators
|
||||
*/
|
||||
iterator begin() noexcept { return m_ht.begin(); }
|
||||
const_iterator begin() const noexcept { return m_ht.begin(); }
|
||||
const_iterator cbegin() const noexcept { return m_ht.cbegin(); }
|
||||
|
||||
iterator end() noexcept { return m_ht.end(); }
|
||||
const_iterator end() const noexcept { return m_ht.end(); }
|
||||
const_iterator cend() const noexcept { return m_ht.cend(); }
|
||||
|
||||
reverse_iterator rbegin() noexcept { return m_ht.rbegin(); }
|
||||
const_reverse_iterator rbegin() const noexcept { return m_ht.rbegin(); }
|
||||
const_reverse_iterator rcbegin() const noexcept { return m_ht.rcbegin(); }
|
||||
|
||||
reverse_iterator rend() noexcept { return m_ht.rend(); }
|
||||
const_reverse_iterator rend() const noexcept { return m_ht.rend(); }
|
||||
const_reverse_iterator rcend() const noexcept { return m_ht.rcend(); }
|
||||
|
||||
|
||||
/*
|
||||
* Capacity
|
||||
*/
|
||||
bool empty() const noexcept { return m_ht.empty(); }
|
||||
size_type size() const noexcept { return m_ht.size(); }
|
||||
size_type max_size() const noexcept { return m_ht.max_size(); }
|
||||
|
||||
/*
|
||||
* Modifiers
|
||||
*/
|
||||
void clear() noexcept { m_ht.clear(); }
|
||||
|
||||
|
||||
|
||||
std::pair<iterator, bool> insert(const value_type& value) { return m_ht.insert(value); }
|
||||
std::pair<iterator, bool> insert(value_type&& value) { return m_ht.insert(std::move(value)); }
|
||||
|
||||
iterator insert(const_iterator hint, const value_type& value) {
|
||||
return m_ht.insert(hint, value);
|
||||
}
|
||||
|
||||
iterator insert(const_iterator hint, value_type&& value) {
|
||||
return m_ht.insert(hint, std::move(value));
|
||||
}
|
||||
|
||||
template<class InputIt>
|
||||
void insert(InputIt first, InputIt last) { m_ht.insert(first, last); }
|
||||
void insert(std::initializer_list<value_type> ilist) { m_ht.insert(ilist.begin(), ilist.end()); }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Due to the way elements are stored, emplace will need to move or copy the key-value once.
|
||||
* The method is equivalent to insert(value_type(std::forward<Args>(args)...));
|
||||
*
|
||||
* Mainly here for compatibility with the std::unordered_map interface.
|
||||
*/
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> emplace(Args&&... args) { return m_ht.emplace(std::forward<Args>(args)...); }
|
||||
|
||||
/**
|
||||
* Due to the way elements are stored, emplace_hint will need to move or copy the key-value once.
|
||||
* The method is equivalent to insert(hint, value_type(std::forward<Args>(args)...));
|
||||
*
|
||||
* Mainly here for compatibility with the std::unordered_map interface.
|
||||
*/
|
||||
template<class... Args>
|
||||
iterator emplace_hint(const_iterator hint, Args&&... args) {
|
||||
return m_ht.emplace_hint(hint, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/**
|
||||
* When erasing an element, the insert order will be preserved and no holes will be present in the container
|
||||
* returned by 'values_container()'.
|
||||
*
|
||||
* The method is in O(n), if the order is not important 'unordered_erase(...)' method is faster with an O(1)
|
||||
* average complexity.
|
||||
*/
|
||||
iterator erase(iterator pos) { return m_ht.erase(pos); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*/
|
||||
iterator erase(const_iterator pos) { return m_ht.erase(pos); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*/
|
||||
iterator erase(const_iterator first, const_iterator last) { return m_ht.erase(first, last); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*/
|
||||
size_type erase(const key_type& key) { return m_ht.erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup to the value if you already have the hash.
|
||||
*/
|
||||
size_type erase(const key_type& key, std::size_t precalculated_hash) {
|
||||
return m_ht.erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc erase(iterator pos)
|
||||
*
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type erase(const K& key) { return m_ht.erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc erase(const key_type& key, std::size_t precalculated_hash)
|
||||
*
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type erase(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void swap(ordered_set& other) { other.m_ht.swap(m_ht); }
|
||||
|
||||
/*
|
||||
* Lookup
|
||||
*/
|
||||
size_type count(const Key& key) const { return m_ht.count(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
size_type count(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.count(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type count(const K& key) const { return m_ht.count(key); }
|
||||
|
||||
/**
|
||||
* @copydoc count(const K& key) const
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type count(const K& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.count(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
iterator find(const Key& key) { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
iterator find(const Key& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
const_iterator find(const Key& key) const { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
const_iterator find(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.find(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
iterator find(const K& key) { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
iterator find(const K& key, std::size_t precalculated_hash) { return m_ht.find(key, precalculated_hash); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const_iterator find(const K& key) const { return m_ht.find(key); }
|
||||
|
||||
/**
|
||||
* @copydoc find(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
const_iterator find(const K& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.find(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::pair<iterator, iterator> equal_range(const Key& key) { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
std::pair<iterator, iterator> equal_range(const Key& key, std::size_t precalculated_hash) {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& key) const { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const Key& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
std::pair<const_iterator, const_iterator> equal_range(const Key& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<iterator, iterator> equal_range(const K& key) { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<iterator, iterator> equal_range(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<const_iterator, const_iterator> equal_range(const K& key) const { return m_ht.equal_range(key); }
|
||||
|
||||
/**
|
||||
* @copydoc equal_range(const K& key, std::size_t precalculated_hash)
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
std::pair<const_iterator, const_iterator> equal_range(const K& key, std::size_t precalculated_hash) const {
|
||||
return m_ht.equal_range(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Bucket interface
|
||||
*/
|
||||
size_type bucket_count() const { return m_ht.bucket_count(); }
|
||||
size_type max_bucket_count() const { return m_ht.max_bucket_count(); }
|
||||
|
||||
|
||||
/*
|
||||
* Hash policy
|
||||
*/
|
||||
float load_factor() const { return m_ht.load_factor(); }
|
||||
float max_load_factor() const { return m_ht.max_load_factor(); }
|
||||
void max_load_factor(float ml) { m_ht.max_load_factor(ml); }
|
||||
|
||||
void rehash(size_type count) { m_ht.rehash(count); }
|
||||
void reserve(size_type count) { m_ht.reserve(count); }
|
||||
|
||||
|
||||
/*
|
||||
* Observers
|
||||
*/
|
||||
hasher hash_function() const { return m_ht.hash_function(); }
|
||||
key_equal key_eq() const { return m_ht.key_eq(); }
|
||||
|
||||
|
||||
/*
|
||||
* Other
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert a const_iterator to an iterator.
|
||||
*/
|
||||
iterator mutable_iterator(const_iterator pos) {
|
||||
return m_ht.mutable_iterator(pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requires index <= size().
|
||||
*
|
||||
* Return an iterator to the element at index. Return end() if index == size().
|
||||
*/
|
||||
iterator nth(size_type index) { return m_ht.nth(index); }
|
||||
|
||||
/**
|
||||
* @copydoc nth(size_type index)
|
||||
*/
|
||||
const_iterator nth(size_type index) const { return m_ht.nth(index); }
|
||||
|
||||
|
||||
/**
|
||||
* Return const_reference to the first element. Requires the container to not be empty.
|
||||
*/
|
||||
const_reference front() const { return m_ht.front(); }
|
||||
|
||||
/**
|
||||
* Return const_reference to the last element. Requires the container to not be empty.
|
||||
*/
|
||||
const_reference back() const { return m_ht.back(); }
|
||||
|
||||
|
||||
/**
|
||||
* Only available if ValueTypeContainer is a std::vector. Same as calling 'values_container().data()'.
|
||||
*/
|
||||
template<class U = values_container_type, typename std::enable_if<tsl::detail_ordered_hash::is_vector<U>::value>::type* = nullptr>
|
||||
const typename values_container_type::value_type* data() const noexcept { return m_ht.data(); }
|
||||
|
||||
/**
|
||||
* Return the container in which the values are stored. The values are in the same order as the insertion order
|
||||
* and are contiguous in the structure, no holes (size() == values_container().size()).
|
||||
*/
|
||||
const values_container_type& values_container() const noexcept { return m_ht.values_container(); }
|
||||
|
||||
template<class U = values_container_type, typename std::enable_if<tsl::detail_ordered_hash::is_vector<U>::value>::type* = nullptr>
|
||||
size_type capacity() const noexcept { return m_ht.capacity(); }
|
||||
|
||||
void shrink_to_fit() { m_ht.shrink_to_fit(); }
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Insert the value before pos shifting all the elements on the right of pos (including pos) one position
|
||||
* to the right.
|
||||
*
|
||||
* Amortized linear time-complexity in the distance between pos and end().
|
||||
*/
|
||||
std::pair<iterator, bool> insert_at_position(const_iterator pos, const value_type& value) {
|
||||
return m_ht.insert_at_position(pos, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc insert_at_position(const_iterator pos, const value_type& value)
|
||||
*/
|
||||
std::pair<iterator, bool> insert_at_position(const_iterator pos, value_type&& value) {
|
||||
return m_ht.insert_at_position(pos, std::move(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc insert_at_position(const_iterator pos, const value_type& value)
|
||||
*
|
||||
* Same as insert_at_position(pos, value_type(std::forward<Args>(args)...), mainly
|
||||
* here for coherence.
|
||||
*/
|
||||
template<class... Args>
|
||||
std::pair<iterator, bool> emplace_at_position(const_iterator pos, Args&&... args) {
|
||||
return m_ht.emplace_at_position(pos, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pop_back() { m_ht.pop_back(); }
|
||||
|
||||
/**
|
||||
* Faster erase operation with an O(1) average complexity but it doesn't preserve the insertion order.
|
||||
*
|
||||
* If an erasure occurs, the last element of the map will take the place of the erased element.
|
||||
*/
|
||||
iterator unordered_erase(iterator pos) { return m_ht.unordered_erase(pos); }
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(iterator pos)
|
||||
*/
|
||||
iterator unordered_erase(const_iterator pos) { return m_ht.unordered_erase(pos); }
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(iterator pos)
|
||||
*/
|
||||
size_type unordered_erase(const key_type& key) { return m_ht.unordered_erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(iterator pos)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
size_type unordered_erase(const key_type& key, std::size_t precalculated_hash) {
|
||||
return m_ht.unordered_erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(iterator pos)
|
||||
*
|
||||
* This overload only participates in the overload resolution if the typedef KeyEqual::is_transparent exists.
|
||||
* If so, K must be hashable and comparable to Key.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type unordered_erase(const K& key) { return m_ht.unordered_erase(key); }
|
||||
|
||||
/**
|
||||
* @copydoc unordered_erase(const K& key)
|
||||
*
|
||||
* Use the hash value 'precalculated_hash' instead of hashing the key. The hash value should be the same
|
||||
* as hash_function()(key). Usefull to speed-up the lookup if you already have the hash.
|
||||
*/
|
||||
template<class K, class KE = KeyEqual, typename std::enable_if<has_is_transparent<KE>::value>::type* = nullptr>
|
||||
size_type unordered_erase(const K& key, std::size_t precalculated_hash) {
|
||||
return m_ht.unordered_erase(key, precalculated_hash);
|
||||
}
|
||||
|
||||
|
||||
|
||||
friend bool operator==(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht == rhs.m_ht; }
|
||||
friend bool operator!=(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht != rhs.m_ht; }
|
||||
friend bool operator<(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht < rhs.m_ht; }
|
||||
friend bool operator<=(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht <= rhs.m_ht; }
|
||||
friend bool operator>(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht > rhs.m_ht; }
|
||||
friend bool operator>=(const ordered_set& lhs, const ordered_set& rhs) { return lhs.m_ht >= rhs.m_ht; }
|
||||
|
||||
friend void swap(ordered_set& lhs, ordered_set& rhs) { lhs.swap(rhs); }
|
||||
|
||||
private:
|
||||
ht m_ht;
|
||||
};
|
||||
|
||||
} // end namespace tsl
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user