libostd/ostd/map.hh

205 lines
6.1 KiB
C++
Raw Normal View History

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