I use Howard Hinnant a nice small arena based dispenser , short_alloc .
It seemed to me that the transfer-transfer from a vector that has outgrown its arena and, thus, is distributed across the heap, can be performed using the usual quick transition destination (i.e., capturing target resources). However, it is not:
typedef arena<16> arena_type; typedef short_alloc<int, 16> alloc_type; typedef std::vector<int, alloc_type> vec_type; arena_type arena1, arena2; vec_type vec1(alloc_type(arena1)), vec2(alloc_type(arena2)); vec1.resize(100); void* data = vec1.data(); vec2 = std::move(vec1); assert(vec2.data() == data);
As explained in this answer , this is due to a vector displacement assignment operator comparing two allocators (note that propagate_on_container_move_assignment is std::false_type ). Since the two allocators do not compare the same (because they have different arenas), the target vector must allocate memory and move the values โโone by one.
The desired behavior is achieved by changing the equality operator to
template <class T1, size_t N1, class T2, size_t N2> bool operator==(const short_alloc<T1, N1>& x, const short_alloc<T2, N2>& y) noexcept { return N1 == N2 && (&x.a_ == &y.a_ || y.a_.on_heap()); }
where on_heap() checks to see if the distributor is using its arena.
This solution looks pretty hacky (note, for example, that equality is not symmetrical), can / will I shoot in the leg by doing this? Is there an elegant solution?
c ++ memory-management c ++ 11 move-semantics allocator
marton78
source share