foonathan/memory

Question re: container allocator copying

Closed this issue · 1 comments

I'm trying to understand how to control allocator propagation.

I have code that looks roughly like this:


MyAllocator allocA;
MyContainer containerA;

{
    MyAllocator allocB;
    MyContainer containerB;

    // Not shown: fill in containerB with various values.
    // Afterwards:

    // Copy the content of B to A. 
    containerA = containerB;
}

// Now use containerA - crash!

The reason for the crash, as I understand it, is that containerA assignment gives it a reference to allocB, which has gone out of scope.
And the reason the allocator is propagated is:

template <class RawAllocator>
struct propagation_traits
{
    // ...

    using propagate_on_container_copy_assignment = // ... something ultimately resulting in std::true_type
}

I have read the blog post talking about this, so I think this default is in the name of efficiency?

This seems to be the default behavior for all foonathan::memory STL containers.
But how would I change it in my case?

Do I need to write a propagation_traits<MyAllocator> ?

The behavior I want is for containerA to continue using allocatorA, but get a copy of containerB's contents.

I have read the blog post talking about this, so I think this default is in the name of efficiency?

Yes, efficiency and based on the assumption that you're having a single/few somewhat global allocators that outlives everything else. I have somewhat warmed up to the idea of preventing propagation, but I still don't like it.

Do I need to write a propagation_traits ?

That, or add propagate_on_container_copy_assignment members to MyAllocator. Of course, this only works if it is truly MyAllocator and not foonathan:::memory::*. In the latter case, it might be useful to add a non_propagated<Allocator> or something. You can also just keep propagation and use .assign() as opposed to operator= when necessary.

Note that back when I initially wrote it, std::pmr::memory_resource wasn't a thing. If you're writing your own allocators, you can just use that instead - the interface is pretty similar.