2015-06-14 01:46:46 +00:00
|
|
|
/* Associative array for OctaSTD. Implemented as a hash table.
|
|
|
|
*
|
|
|
|
* This file is part of OctaSTD. See COPYING.md for futher information.
|
|
|
|
*/
|
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#ifndef OSTD_MAP_HH
|
|
|
|
#define OSTD_MAP_HH
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#include "ostd/types.hh"
|
|
|
|
#include "ostd/utility.hh"
|
|
|
|
#include "ostd/memory.hh"
|
|
|
|
#include "ostd/functional.hh"
|
|
|
|
#include "ostd/initializer_list.hh"
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2015-07-13 19:08:55 +00:00
|
|
|
#include "ostd/internal/hashtable.hh"
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
namespace ostd {
|
2015-06-14 01:46:46 +00:00
|
|
|
|
|
|
|
namespace detail {
|
2015-06-16 00:46:34 +00:00
|
|
|
template<typename K, typename T, typename A> struct MapBase {
|
2016-06-23 18:18:35 +00:00
|
|
|
using Element = Pair<K const, T>;
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
static inline K const &get_key(Element &e) {
|
2015-06-14 01:46:46 +00:00
|
|
|
return e.first;
|
|
|
|
}
|
|
|
|
static inline T &get_data(Element &e) {
|
|
|
|
return e.second;
|
|
|
|
}
|
|
|
|
template<typename U>
|
2015-06-16 00:46:34 +00:00
|
|
|
static inline void set_key(Element &e, U &&key, A &alloc) {
|
2015-07-05 22:59:36 +00:00
|
|
|
allocator_destroy(alloc, &e);
|
|
|
|
allocator_construct(alloc, &e, forward<U>(key), move(T()));
|
2015-06-14 01:46:46 +00:00
|
|
|
}
|
2015-06-14 23:18:08 +00:00
|
|
|
static inline void swap_elem(Element &a, Element &b) {
|
2016-07-02 03:56:23 +00:00
|
|
|
swap_adl(const_cast<K &>(a.first), const_cast<K &>(b.first));
|
|
|
|
swap_adl(a.second, b.second);
|
2015-06-14 23:18:08 +00:00
|
|
|
}
|
2015-06-14 01:46:46 +00:00
|
|
|
};
|
|
|
|
|
2015-06-18 01:32:43 +00:00
|
|
|
template<
|
|
|
|
typename K, typename T, typename H,
|
|
|
|
typename C, typename A, bool IsMultihash
|
2015-07-05 22:59:36 +00:00
|
|
|
> struct MapImpl: detail::Hashtable<detail::MapBase<K, T, A>,
|
2016-06-23 18:18:35 +00:00
|
|
|
Pair<K const, T>, K, T, H, C, A, IsMultihash
|
2015-06-18 01:32:43 +00:00
|
|
|
> {
|
|
|
|
private:
|
2015-07-05 22:59:36 +00:00
|
|
|
using Base = detail::Hashtable<detail::MapBase<K, T, A>,
|
2016-06-23 18:18:35 +00:00
|
|
|
Pair<K const, T>, K, T, H, C, A, IsMultihash
|
2015-06-18 01:32:43 +00:00
|
|
|
>;
|
|
|
|
|
|
|
|
public:
|
|
|
|
using Key = K;
|
|
|
|
using Mapped = T;
|
2015-07-13 19:07:14 +00:00
|
|
|
using Size = ostd::Size;
|
2015-07-05 22:59:36 +00:00
|
|
|
using Difference = Ptrdiff;
|
2015-06-18 01:32:43 +00:00
|
|
|
using Hasher = H;
|
|
|
|
using KeyEqual = C;
|
2016-06-23 18:18:35 +00:00
|
|
|
using Value = Pair<K const, T>;
|
2015-06-18 01:32:43 +00:00
|
|
|
using Reference = Value &;
|
2015-07-05 22:59:36 +00:00
|
|
|
using Pointer = AllocatorPointer<A>;
|
|
|
|
using ConstPointer = AllocatorConstPointer<A>;
|
2016-06-23 18:18:35 +00:00
|
|
|
using Range = HashRange<Pair<K const, T>>;
|
|
|
|
using ConstRange = HashRange<Pair<K const, T> const>;
|
|
|
|
using LocalRange = BucketRange<Pair<K const, T>>;
|
|
|
|
using ConstLocalRange = BucketRange<Pair<K const, T> const>;
|
2015-06-18 01:32:43 +00:00
|
|
|
using Allocator = A;
|
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
explicit MapImpl(Size size, H const &hf = H(),
|
|
|
|
C const &eqf = C(), A const &alloc = A()
|
2015-06-18 01:32:43 +00:00
|
|
|
): Base(size, hf, eqf, alloc) {}
|
|
|
|
|
|
|
|
MapImpl(): MapImpl(0) {}
|
2016-06-23 18:18:35 +00:00
|
|
|
explicit MapImpl(A const &alloc): MapImpl(0, H(), C(), alloc) {}
|
2015-06-18 01:32:43 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl(Size size, A const &alloc):
|
2015-06-18 01:32:43 +00:00
|
|
|
MapImpl(size, H(), C(), alloc) {}
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl(Size size, H const &hf, A const &alloc):
|
2015-06-18 01:32:43 +00:00
|
|
|
MapImpl(size, hf, C(), alloc) {}
|
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl(MapImpl const &m): Base(m,
|
2015-07-05 22:59:36 +00:00
|
|
|
allocator_container_copy(m.get_alloc())) {}
|
2015-06-18 01:32:43 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl(MapImpl const &m, A const &alloc): Base(m, alloc) {}
|
2015-06-18 01:32:43 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
MapImpl(MapImpl &&m): Base(move(m)) {}
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl(MapImpl &&m, A const &alloc): Base(move(m), alloc) {}
|
2015-06-18 01:32:43 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename R, typename = EnableIf<
|
2016-01-13 18:09:21 +00:00
|
|
|
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>
|
2016-06-23 18:18:35 +00:00
|
|
|
>> MapImpl(R range, Size size = 0, H const &hf = H(),
|
|
|
|
C const &eqf = C(), A const &alloc = A()
|
2015-07-05 22:59:36 +00:00
|
|
|
): Base(size ? size : detail::estimate_hrsize(range),
|
2015-06-18 01:32:43 +00:00
|
|
|
hf, eqf, alloc) {
|
|
|
|
for (; !range.empty(); range.pop_front())
|
|
|
|
Base::emplace(range.front());
|
|
|
|
Base::rehash_up();
|
|
|
|
}
|
2015-06-16 20:36:16 +00:00
|
|
|
|
2015-06-18 01:32:43 +00:00
|
|
|
template<typename R>
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl(R range, Size size, A const &alloc)
|
2015-06-18 01:32:43 +00:00
|
|
|
: MapImpl(range, size, H(), C(), alloc) {}
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2015-06-18 01:32:43 +00:00
|
|
|
template<typename R>
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl(R range, Size size, H const &hf, A const &alloc)
|
2015-06-18 01:32:43 +00:00
|
|
|
: MapImpl(range, size, hf, C(), alloc) {}
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
MapImpl(InitializerList<Value> init, Size size = 0,
|
2016-06-23 18:18:35 +00:00
|
|
|
H const &hf = H(), C const &eqf = C(), A const &alloc = A()
|
2015-07-05 22:59:36 +00:00
|
|
|
): MapImpl(iter(init), size, hf, eqf, alloc) {}
|
2015-06-15 00:35:37 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl(InitializerList<Value> init, Size size, A const &alloc)
|
2015-07-05 22:59:36 +00:00
|
|
|
: MapImpl(iter(init), size, H(), C(), alloc) {}
|
2015-06-15 00:35:37 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl(InitializerList<Value> init, Size size, H const &hf,
|
|
|
|
A const &alloc
|
2015-07-05 22:59:36 +00:00
|
|
|
): MapImpl(iter(init), size, hf, C(), alloc) {}
|
2015-06-16 18:12:03 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
MapImpl &operator=(MapImpl const &m) {
|
2015-06-18 01:32:43 +00:00
|
|
|
Base::operator=(m);
|
|
|
|
return *this;
|
|
|
|
}
|
2015-06-16 18:12:03 +00:00
|
|
|
|
2015-06-18 01:32:43 +00:00
|
|
|
MapImpl &operator=(MapImpl &&m) {
|
2015-07-05 22:59:36 +00:00
|
|
|
Base::operator=(move(m));
|
2015-06-18 01:32:43 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2015-06-16 18:12:03 +00:00
|
|
|
|
2015-07-05 22:59:36 +00:00
|
|
|
template<typename R, typename = EnableIf<
|
2016-01-13 18:09:21 +00:00
|
|
|
IsInputRange<R> && IsConvertible<RangeReference<R>, Value>
|
2015-06-29 20:56:13 +00:00
|
|
|
>> MapImpl &operator=(R range) {
|
2015-06-18 01:32:43 +00:00
|
|
|
Base::assign_range(range);
|
|
|
|
return *this;
|
|
|
|
}
|
2015-06-14 23:18:08 +00:00
|
|
|
|
2015-06-18 01:32:43 +00:00
|
|
|
MapImpl &operator=(InitializerList<Value> il) {
|
|
|
|
Base::assign_init(il);
|
|
|
|
return *this;
|
|
|
|
}
|
2015-06-14 23:18:08 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
T *at(K const &key) {
|
2015-06-18 01:32:43 +00:00
|
|
|
static_assert(!IsMultihash, "at() only allowed on regular maps");
|
|
|
|
return Base::access(key);
|
|
|
|
}
|
2016-06-23 18:18:35 +00:00
|
|
|
T const *at(K const &key) const {
|
2015-06-18 01:32:43 +00:00
|
|
|
static_assert(!IsMultihash, "at() only allowed on regular maps");
|
|
|
|
return Base::access(key);
|
|
|
|
}
|
2015-06-14 03:32:01 +00:00
|
|
|
|
2016-06-23 18:18:35 +00:00
|
|
|
T &operator[](K const &key) {
|
2015-06-18 01:32:43 +00:00
|
|
|
static_assert(!IsMultihash, "operator[] only allowed on regular maps");
|
|
|
|
return Base::access_or_insert(key);
|
|
|
|
}
|
|
|
|
T &operator[](K &&key) {
|
|
|
|
static_assert(!IsMultihash, "operator[] only allowed on regular maps");
|
2015-07-05 22:59:36 +00:00
|
|
|
return Base::access_or_insert(move(key));
|
2015-06-18 01:32:43 +00:00
|
|
|
}
|
2015-06-15 20:06:34 +00:00
|
|
|
|
2015-06-18 01:32:43 +00:00
|
|
|
void swap(MapImpl &v) {
|
|
|
|
Base::swap(v);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2015-06-17 20:25:34 +00:00
|
|
|
template<
|
|
|
|
typename K, typename T,
|
2015-07-05 22:59:36 +00:00
|
|
|
typename H = ToHash<K>,
|
2015-08-02 13:58:49 +00:00
|
|
|
typename C = EqualWithCstr<K>,
|
2016-06-23 18:18:35 +00:00
|
|
|
typename A = Allocator<Pair<K const, T>>
|
2015-07-05 22:59:36 +00:00
|
|
|
> using Map = detail::MapImpl<K, T, H, C, A, false>;
|
2015-06-17 20:25:34 +00:00
|
|
|
|
2015-06-18 01:32:43 +00:00
|
|
|
template<
|
|
|
|
typename K, typename T,
|
2015-07-05 22:59:36 +00:00
|
|
|
typename H = ToHash<K>,
|
2015-08-02 13:58:49 +00:00
|
|
|
typename C = EqualWithCstr<K>,
|
2016-06-23 18:18:35 +00:00
|
|
|
typename A = Allocator<Pair<K const, T>>
|
2015-07-05 22:59:36 +00:00
|
|
|
> using Multimap = detail::MapImpl<K, T, H, C, A, true>;
|
2015-06-17 20:25:34 +00:00
|
|
|
|
2015-07-13 19:07:14 +00:00
|
|
|
} /* namespace ostd */
|
2015-06-14 01:46:46 +00:00
|
|
|
|
2016-02-07 21:17:15 +00:00
|
|
|
#endif
|