support for hashtable assignment ops

master
Daniel Kolesa 2015-06-16 20:44:32 +01:00
parent cfe7450d4b
commit eca4310caf
2 changed files with 88 additions and 12 deletions

View File

@ -152,8 +152,16 @@ namespace detail {
A &get_alloc() { return p_data.second().first().first(); }
const A &get_alloc() const { return p_data.second().first().first(); }
CPA &get_cpalloc() { return p_data.second().first().second().first(); }
const CPA &get_cpalloc() const {
return p_data.second().first().second().first();
}
CHA &get_challoc() { return p_data.second().first().second().second(); }
const CHA &get_challoc() const {
return p_data.second().first().second().second();
}
Hashtable(octa::Size size, const H &hf, const C &eqf, const A &alloc):
p_size(size), p_len(0), p_chunks(nullptr), p_unused(nullptr),
@ -230,6 +238,38 @@ namespace detail {
delete_chunks(p_chunks);
}
Hashtable &operator=(const Hashtable &ht) {
clear();
if (octa::AllocatorPropagateOnContainerCopyAssignment<A>::value) {
if ((get_cpalloc() != ht.get_cpalloc()) && p_size) {
octa::allocator_deallocate(get_cpalloc(),
p_data.first(), p_size);
p_data.first() = octa::allocator_allocate(get_cpalloc(),
p_size);
memset(p_data.first(), 0, p_size * sizeof(Chain *));
}
get_alloc() = ht.get_alloc();
get_cpalloc() = ht.get_cpalloc();
get_challoc() = ht.get_challoc();
}
for (ConstRange range = ht.each(); !range.empty(); range.pop_front())
emplace(range.front());
return *this;
}
Hashtable &operator=(Hashtable &&ht) {
clear();
octa::swap(p_size, ht.p_size);
octa::swap(p_len, ht.p_len);
octa::swap(p_chunks, ht.p_chunks);
octa::swap(p_unused, ht.p_unused);
octa::swap(p_data.first(), ht.p_data.first());
octa::swap(p_data.second().second(), ht.p_data.second().second());
if (octa::AllocatorPropagateOnContainerMoveAssignment<A>::value)
octa::swap(p_data.second().first(), ht.p_data.second().first());
return *this;
}
bool empty() const { return p_len == 0; }
octa::Size size() const { return p_len; }
Size max_size() const { return Size(~0) / sizeof(E); }
@ -403,10 +443,14 @@ namespace detail {
return Range(p_data.first(), p_data.first() + bucket_count());
}
ConstRange each() const {
return ConstRange(p_data.first(), p_data.first() + bucket_count());
using Chain = octa::detail::HashChain<const E>;
return ConstRange((Chain **)p_data.first(),
(Chain **)(p_data.first() + bucket_count()));
}
ConstRange ceach() const {
return ConstRange(p_data.first(), p_data.first() + bucket_count());
using Chain = octa::detail::HashChain<const E>;
return ConstRange((Chain **)p_data.first(),
(Chain **)(p_data.first() + bucket_count()));
}
LocalRange each(octa::Size n) {
@ -414,23 +458,25 @@ namespace detail {
return LocalRange(p_data.first()[n]);
}
ConstLocalRange each(octa::Size n) const {
using Chain = octa::detail::HashChain<const E>;
if (n >= p_size) return ConstLocalRange();
return ConstLocalRange(p_data.first()[n]);
return ConstLocalRange((Chain *)p_data.first()[n]);
}
ConstLocalRange ceach(octa::Size n) const {
using Chain = octa::detail::HashChain<const E>;
if (n >= p_size) return ConstLocalRange();
return ConstLocalRange(p_data.first()[n]);
return ConstLocalRange((Chain *)p_data.first()[n]);
}
void swap(Hashtable &h) {
octa::swap(p_size, h.p_size);
octa::swap(p_len, h.p_len);
octa::swap(p_chunks, h.p_chunks);
octa::swap(p_unused, h.p_unused);
octa::swap(p_data.first(), h.p_data.first());
octa::swap(p_data.second().second(), h.p_data.second().second());
void swap(Hashtable &ht) {
octa::swap(p_size, ht.p_size);
octa::swap(p_len, ht.p_len);
octa::swap(p_chunks, ht.p_chunks);
octa::swap(p_unused, ht.p_unused);
octa::swap(p_data.first(), ht.p_data.first());
octa::swap(p_data.second().second(), ht.p_data.second().second());
if (octa::AllocatorPropagateOnContainerSwap<A>::value)
octa::swap(p_data.second().first(), h.p_data.second().first());
octa::swap(p_data.second().first(), ht.p_data.second().first());
}
};
} /* namespace detail */

View File

@ -118,6 +118,36 @@ public:
const A &alloc
): Map(octa::each(init), size, hf, C(), alloc) {}
Map &operator=(const Map &m) {
p_table = m.p_table;
return *this;
}
Map &operator=(Map &&m) {
p_table = octa::move(m.p_table);
return *this;
}
template<typename R>
octa::EnableIf<
octa::IsInputRange<R>::value &&
octa::IsConvertible<RangeReference<R>, Value>::value,
Map &
> operator=(R range) {
clear();
for (; !range.empty(); range.pop_front())
emplace(range.front());
return *this;
}
Map &operator=(InitializerList<Value> il) {
Value *beg = il.begin(), *end = il.end();
clear();
while (beg != end)
emplace(*beg++);
return *this;
}
bool empty() const { return p_table.empty(); }
octa::Size size() const { return p_table.size(); }
octa::Size max_size() const { return p_table.max_size(); }